【问题标题】:Service worker error: event already responded to服务工作者错误:事件已响应
【发布时间】:2017-10-19 20:57:08
【问题描述】:

我不断收到此错误:

Uncaught (in promise) DOMException: Failed to execute 'respondWith' on 'FetchEvent': 该事件已被响应。

我知道如果 fetch 函数中发生异步操作,Service Worker 会自动响应,但我无法完全确定这段代码中的哪一点是违规者:

importScripts('cache-polyfill.js');

self.addEventListener('fetch', function(event) {

  var location = self.location;

  console.log("loc", location)

  self.clients.matchAll({includeUncontrolled: true}).then(clients => {
    for (const client of clients) {
      const clientUrl = new URL(client.url);
      console.log("SO", clientUrl);
      if(clientUrl.searchParams.get("url") != undefined && clientUrl.searchParams.get("url") != '') {
        location = client.url;
      }
    }

  console.log("loc2", location)

  var url = new URL(location).searchParams.get('url').toString();

  console.log(event.request.hostname);
  var toRequest = event.request.url;
  console.log("Req:", toRequest);

  var parser2 = new URL(location);
  var parser3 = new URL(url);

  var parser = new URL(toRequest);

  console.log("if",parser.host,parser2.host,parser.host === parser2.host);
  if(parser.host === parser2.host) {
    toRequest = toRequest.replace('https://booligoosh.github.io',parser3.protocol + '//' +  parser3.host);
    console.log("ifdone",toRequest);
  }

  console.log("toRequest:",toRequest);

  event.respondWith(httpGet('https://cors-anywhere.herokuapp.com/' + toRequest));
  });
});

function httpGet(theUrl) {
    /*var xmlHttp = new XMLHttpRequest();
    xmlHttp.open( "GET", theUrl, false ); // false for synchronous request
    xmlHttp.send( null );
    return xmlHttp.responseText;*/
    return(fetch(theUrl));
}

任何帮助将不胜感激。

【问题讨论】:

    标签: javascript runtime-error service-worker service-worker-events


    【解决方案1】:

    问题是您对event.respondWith() 的调用位于顶级promise 的.then() 子句中,这意味着它将在顶级promise 解决后异步执行。为了获得您期望的行为,event.respondWith() 需要作为fetch 事件处理程序执行的一部分同步执行。

    您的承诺中的逻辑有点难以遵循,所以我不确定您要完成什么,但总的来说您可以遵循以下模式:

    self.addEventListerner('fetch', event => {
      // Perform any synchronous checks to see whether you want to respond.
      // E.g., check the value of event.request.url.
      if (event.request.url.includes('something')) {
        const promiseChain = doSomethingAsync()
          .then(() => doSomethingAsyncThatReturnsAURL())
          .then(someUrl => fetch(someUrl));
          // Instead of fetch(), you could have called caches.match(),
          // or anything else that returns a promise for a Response.
    
        // Synchronously call event.respondWith(), passing in the
        // async promise chain.
        event.respondWith(promiseChain);
      }
    });
    

    这是一般的想法。 (如果你最终将 promise 替换为 async/await,代码看起来会更加简洁。)

    【讨论】:

      【解决方案2】:

      我在 fetch 处理程序中尝试使用 async/await 时也偶然发现了这个错误。正如 Jeff 在他的回答中提到的,event.respondWith 必须被同步调用,并且参数可以是返回解析为响应的承诺的任何内容。由于异步函数确实返回了一个 Promise,因此您所要做的就是将 fetch 逻辑包装在一个异步函数中,该函数有时会返回一个响应对象并使用该处理程序调用 event.respondWith

      async function handleRequest(request) {
        const response = await fetch(request)
      
        // ...perform additional logic
      
        return response
      }
      
      self.addEventListener("fetch", event => {
        event.respondWith(handleRequest(event.request));
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-02-27
        • 1970-01-01
        • 2019-01-04
        • 2020-06-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多