Uncaught DOMException (in promise) - 在 serviceworker 中劫持特定的 GraphQL 请求

Uncaught DOMException (in promise) - Hijack specific GraphQL request in the serviceworker

我尝试通过 service-worker 劫持特定的 GraphQL-Request 来伪造来自我的 IndexedDB 中的数据的响应,但我收到一个错误,指出事件已经得到响应。提取对缓存文件有效,如果提取的数据不在缓存中,它将使用网络。如果没有网络,则会有离线回退。我如何安排我的承诺,我也可以劫持对我的 GraphQL API 和特定查询 (operationName) 的请求,因为我似乎搞砸了异步 event.respondWith 调用?

self.addEventListener('fetch', function (event) {
    if (event.request.url === __GRAPHQL_URL__) {
        event.request.clone().json().then(({operationName, variables}) => {
            switch (operationName) {
                case 'getOfflineFacilities':
                    //when a fetch is matching there will be the error
                    event.respondWith(serveOfflineFacilities());
            }
        });
    }else{

        event.respondWith(
            caches.match(event.request).then(function (response) {
                console.log("cache or network fallback");
                return response || fetch(event.request);
            }).catch(function () {
                console.log("offline fallback");
                return caches.match('/index.html');
            })
        );
    }
});

GraphQL 查询命中 __GRAPHQL_URL__ 和我的 operationName

时出错

sw.js:41 Uncaught (in promise) DOMException: Failed to execute 'respondWith' on 'FetchEvent': The event has already been responded to.

它的文档很少,但您需要调用仅在事件处理程序调用期间设置的 respondWith method immediately in the handler. If the event handler exits and respondWith had not been called, the request will be handled so that the default response is served. respondWith will check the dispatch flag - 当您仅从 promise 回调中调用它时,您将获得“该事件已响应”异常。

因此您需要更改代码以将整个承诺传递给 respondWith:

if (event.request.url === __GRAPHQL_URL__) {
    event.respondWith(event.request.clone().json().then(({operationName, variables}) => {
//  ^^^^^^^^^^^^^^^^^^
        switch (operationName) {
            case 'getOfflineFacilities':
                return serveOfflineFacilities();
//              ^^^^^^
        }
    }));
//    ^
}