Javascript 如何在不使用服务工作者的情况下钩住fetch方法?

Javascript 如何在不使用服务工作者的情况下钩住fetch方法?,javascript,fetch,Javascript,Fetch,如何在不使用服务工作者的情况下钩住fetch方法 我知道我可以用服务人员来做这件事,但还有其他方法吗?不使用服务人员 重要: 我想在实际从中获取资源之前做一些事情 类似服务器的从其他源获取响应 如果我使用的某个供应商模块正在使用fetch,我也希望覆盖该模块 服务人员方式 非服务人员方式 我想到的一件事是包装window.fetch方法,但我不喜欢这个解决方案 window.fetch = async function(requestUrl) { // Try to get the resp

如何在不使用服务工作者的情况下钩住fetch方法

我知道我可以用服务人员来做这件事,但还有其他方法吗?不使用服务人员

重要

  • 我想在实际从中获取资源之前做一些事情 类似服务器的从其他源获取响应
  • 如果我使用的某个供应商模块正在使用
    fetch
    ,我也希望覆盖该模块
  • 服务人员方式 非服务人员方式 我想到的一件事是包装
    window.fetch
    方法,但我不喜欢这个解决方案

    window.fetch = async function(requestUrl) {
      // Try to get the response from a cache.
      const cache = await caches.open('dynamic-v1');
      const url = new URL(requestUrl);
      const cachedResponse = await cache.match(url.pathname);
    
      if (cachedResponse) {
        return cachedResponse;
      }
    
      return fetch(requestUrl);
    }
    

    Ofc这个例子只是理论上的,所以有什么想法吗?

    这不是这个问题的真正答案,但无论如何,我会把它贴在这里,因为它可能会帮助一些人

    因此,我真正需要做的是在客户端(而不是在软件中)处理一些东西,我通过使用
    MessageChannel
    让软件和客户端双向通信来实现这一点

    我所做的:
  • 将sw设置为在获取事件时侦听
  • 在允许客户端发送响应的承诺中创建MessageChannel
  • 使用MessageChannel向客户端发送获取事件
  • 客户做的事情
  • 将响应发送回sw witch MessageChannel
  • 你可以从这个谷歌的例子中得到基本的想法:

    最重要的部分是将工作委托给客户机,让其在另一个端口上响应,从而使整个过程实现如下承诺:

    // This wraps the message posting/response in a promise, which will resolve if the response doesn't
    // contain an error, and reject with the error if it does. If you'd prefer, it's possible to call
    // controller.postMessage() and set up the onmessage handler independently of a promise, but this is
    // a convenient wrapper.
    return await new Promise((resolve, reject) => {
      let messageChannel = new MessageChannel();
      messageChannel.port1.onmessage = function (event) {
        if (event.data && event.data.error) {
          reject(event.data.error);
        } else {
          resolve(event.data);
        }
      };
    
      // This sends the message data as well as transferring messageChannel.port2 to the client.
      // The client can then use the transferred port to reply via postMessage(), which
      // will in turn trigger the onmessage handler on messageChannel.port1.
      // See https://html.spec.whatwg.org/multipage/workers.html#dom-worker-postmessage
      client.postMessage(message, [messageChannel.port2]);
    
      // Set up the timeout
      setTimeout(() => {
        messageChannel.port1.close();
        messageChannel.port2.close();
    
        reject('Promise timed out after ' + this.timeoutAfter + ' ms');
    
      }, this.timeoutAfter);
    });
    
    如果你想看看我的用例,它可以在工作完成的地方找到


    请随意提问,我很乐意回答

    创建一个新函数
    myFetch
    ,并调用该函数,而不是
    fetch
    。这是我不想做的,如果我使用的是某个供应商模块正在使用
    fetch
    ,该怎么办?“我也希望覆盖这个问题,如果你希望人们知道他们是什么,那么你应该在问题中包括解决方案的所有要求。”MikeMcCaughan说
    // This wraps the message posting/response in a promise, which will resolve if the response doesn't
    // contain an error, and reject with the error if it does. If you'd prefer, it's possible to call
    // controller.postMessage() and set up the onmessage handler independently of a promise, but this is
    // a convenient wrapper.
    return await new Promise((resolve, reject) => {
      let messageChannel = new MessageChannel();
      messageChannel.port1.onmessage = function (event) {
        if (event.data && event.data.error) {
          reject(event.data.error);
        } else {
          resolve(event.data);
        }
      };
    
      // This sends the message data as well as transferring messageChannel.port2 to the client.
      // The client can then use the transferred port to reply via postMessage(), which
      // will in turn trigger the onmessage handler on messageChannel.port1.
      // See https://html.spec.whatwg.org/multipage/workers.html#dom-worker-postmessage
      client.postMessage(message, [messageChannel.port2]);
    
      // Set up the timeout
      setTimeout(() => {
        messageChannel.port1.close();
        messageChannel.port2.close();
    
        reject('Promise timed out after ' + this.timeoutAfter + ' ms');
    
      }, this.timeoutAfter);
    });