我已经完成了一个简单的服务 worker 来延迟对我的 JS 应用程序失败的请求(在 this example 之后)并且它运行良好。
但是当请求成功时我仍然有一个问题:请求完成了两次。我猜是由于 fetch()
调用,一次正常,一次由服务人员执行。
这是一个真正的问题,因为当客户端想要保存数据时,它们被保存了两次...
代码如下:
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
似乎无法等待(并读取)响应。
我走对了吗?如何知道触发 fetchEvent
的请求何时有响应?
最佳答案
您在 promiseChain
内部异步调用 event.respondWith(...)
。
您需要在 fetch
事件处理程序的初始执行期间同步调用 event.respondWith()
。这是向服务 worker 发出的“信号”,它是您的 fetch
处理程序,而不是另一个注册的 fetch
处理程序(或浏览器默认值),它将提供对传入请求的响应.
(当您在初始执行期间同步调用 event.waitUntil(promiseChain)
时,实际上并没有做任何关于响应请求的事情——它只是确保 service worker promiseChain
执行时不会自动终止。)
退一步说,如果您将 workbox.backgroundSync.Plugin
与 workbox.routing.registerRoute( )
,在 example from the docs 之后:
workbox.routing.registerRoute(
/\/sf\/observation$/,
workbox.strategy.networkOnly({
plugins: [new workbox.backgroundSync.Plugin('deferredRequestsQueue')]
}),
'POST'
);
这将告诉 Workbox 拦截任何匹配您的 RegExp 的 POST
请求,尝试使用网络发出这些请求,如果失败,自动排队并通过后台同步 API 重试.
关于javascript - 通过 service-worker 的请求完成了两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50129311/