通过服务工作者的请求完成两次 [英] Requests through service-worker are done twice

查看:132
本文介绍了通过服务工作者的请求完成两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经完成了一个简单的服务工作者来推迟我的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)在初始执行期间同步,实际上并没有做任何关于响应请求的事情 - 它只是确保服务工作者不会在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆