使用serviceworker取消获取请求

问题描述 投票:0回答:1

我有一个 ServiceWorker 可以拦截 Fetch 请求。有时,获取请求注定会失败,因此 ServiceWorker 应该在它到达网络之前取消它。

我的代码如下所示:

async function onFetch(event) {
  const { request } = event;

  const result = handleRequest(request)
    .then(someStuff)
    .catch((err) => {
      const ctrl = new AbortController();
      ctrl.abort('request is doomed');

      const cancellation = fetch(request, { signal: ctrl.signal });
      // cancellation is correctly an AbortError DOMException

      // event.respondWith(cancellation); // results in net::ERR_FAILED
      return cancellation;
    });
  
  return event.waitUntil(result);
}

在没有 Service Worker 的情况下进行的快速实验表明这应该可行:

const ctrl = new AbortController();
ctrl.abort('request is doomed');

fetch('http://localhost', { signal: ctrl: signal });

在上述实验中,DevTools Network面板中的请求被标记为“已取消”,并且没有发出网络请求。

但是,在ServiceWorker中,请求不会被取消(中止信号被完全忽略)并且它会发送到网络。

fetch service-worker abortcontroller
1个回答
0
投票

如果您提供

event.respondWith
一个新的
Response
(或
PromiseLike<Response>
),并且不获取
event.request
,那么您实际上取消了原始请求。

根据您提供的

Response
,这可能会产生方便的副作用,例如取消导航。例如,您可以使用方法
POST
:

取消任何表单提交发出的获取请求
self.addEventListener('fetch', (event) => {
  if (event.request.method === 'POST' && event.request.mode === 'navigate') {
    event.respondWith(new Response(null, { status: 204 }));
  }
});

我们使用 HTTP 状态代码

204 No Content
来阻止此处的导航。根据上下文,其他状态代码可能对您的用例有更方便的语义。

© www.soinside.com 2019 - 2024. All rights reserved.