通过服务工作者的请求完成两次 [英] Requests through service-worker are done twice
问题描述
我已经完成了一个简单的服务工作者来推迟我的JS应用程序失败的请求(在这个例子)并且效果很好。
但是当请求成功时我仍然遇到问题:请求完成两次。由于 fetch()
调用,服务工作者有一次正常和一次。我想是。
I've done a simple service-worker to defer requests that fail for my JS application (following this example) and it works well.
But I still have a problem when requests succeed: the requests are done twice. One time normaly and one time by the service-worker due to the fetch()
call I guess.
它是一个真正的问题,因为当客户想要保存数据时,它们会被保存两次...
It's a real problem because when the client want to save datas, they are saved twice...
以下是代码:
const queue = new workbox.backgroundSync.Queue('deferredRequestsQueue');
const requestsToDefer = [
{ urlPattern: /\/sf\/observation$/, method: 'POST' }
]
function isRequestAllowedToBeDeferred (request) {
for (let i = 0; i < requestsToDefer.length; i++) {
if (request.method && request.method.toLowerCase() === requestsToDefer[i].method.toLowerCase()
&& requestsToDefer[i].urlPattern.test(request.url)) {
return true
}
}
return false
}
self.addEventListener('fetch', (event) => {
if (isRequestAllowedToBeDeferred(event.request)) {
const requestClone = event.request.clone()
const promiseChain = fetch(requestClone)
.catch((err) => {
console.log(`Request added to queue: ${event.request.url}`)
queue.addRequest(event.request)
event.respondWith(new Response({ deferred: true, request: requestClone }))
})
event.waitUntil(promiseChain)
}
})
如何做得好?
编辑:
我想我不必重新 fetch()
请求(因为这是第二个请求的原因)并等待触发 fetchEvent的初始请求的响应
但我不知道该怎么做。 fetchEvent
似乎无法等待(并阅读)回复。
I think I don't have to re-fetch()
the request (because THIS is the cause of the 2nd request) and wait the response of the initial request that triggered the fetchEvent
but I have no idea how to do it. The fetchEvent
seems to have no way to wait (and read) the response.
我是否正确行事?如何知道触发 fetchEvent
的请求何时有响应?
Am I on the right way ? How to know when the request that triggered the fetchEvent
has a response ?
推荐答案
你在 promiseChain
中异步调用 event.respondWith(...)
。
你需要在初步执行 fetch期间同步调用
事件处理程序。这是服务工作者的信号,它是你的 event.respondWith()
fetch
处理程序,而不是另一个注册的 fetch
处理程序(或者浏览器默认值)将提供对传入请求的响应。
You need to call event.respondWith()
synchronously, during the initial execution of the fetch
event handler. That's the "signal" to the service worker that it's your fetch
handler, and not another registered fetch
handler (or the browser default) that will provide the response to the incoming request.
(当您调用 event.waitUntil(promiseChain)$ c时$ c>在初始执行期间同步,实际上并没有做任何关于响应请求的事情 - 它只是确保服务工作者不会在
promiseChain
正在执行。)
(While you're calling event.waitUntil(promiseChain)
synchronously during the initial execution, that doesn't actually do anything with regards to responding to the request—it just ensures that the service worker isn't automatically killed while promiseChain
is executing.)
退后一步,我想如果你使用,你可能会有更好的运气来完成你想要做的事情workbox.backgroundSync.Plugin
以及<$ h $ = c> workbox.routing.registerRoute(),位于来自文档的示例:
Taking a step back, I think you might have better luck accomplishing what you're trying to do if you use the workbox.backgroundSync.Plugin
along with workbox.routing.registerRoute()
, following the example from the docs:
workbox.routing.registerRoute(
/\/sf\/observation$/,
workbox.strategy.networkOnly({
plugins: [new workbox.backgroundSync.Plugin('deferredRequestsQueue')]
}),
'POST'
);
这将告诉Workbox拦截任何 POST
与RegExp匹配的请求,尝试使用网络发出请求,如果失败,则自动排队并通过后台同步API重试它们。
That will tell Workbox to intercept any POST
requests that match your RegExp, attempt to make those requests using the network, and if it fails, to automatically queue up and retry them via the Background Sync API.
这篇关于通过服务工作者的请求完成两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!