如何挂钩到不使用服务工作者的fetch方法?

时间:2018-01-22 07:20:14

标签: javascript fetch

如何挂钩到不使用服务工作者的fetch方法?

我知道我可以使用服务工作者来做,但还有其他方法吗?不使用服务工作者?

重要

  1. 在我真正从中获取资源之前,我想做一些事情 服务器,例如从其他来源获取响应
  2. 如果我正在使用某个使用fetch的供应商模块,我也想覆盖那个
  3. 服务工作者方式

    addEventListener('fetch', event => {
      // Let the browser do its default thing
      // for non-GET requests.
      if (event.request.method != 'GET') return;
    
      // Prevent the default, and handle the request ourselves.
      event.respondWith(async function() {
        // Try to get the response from a cache.
        const cache = await caches.open('dynamic-v1');
        const cachedResponse = await cache.match(event.request);
    
        if (cachedResponse) {
          // If we found a match in the cache, return it, but also
          // update the entry in the cache in the background.
          event.waitUntil(cache.add(event.request));
          return cachedResponse;
        }
    
        // If we didn't find a match in the cache, use the network.
        return fetch(event.request);
      }());
    });
    

    非服务工作者方式

    我想到的一件事是包装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这个例子只是理论上的,所以有什么想法吗?

1 个答案:

答案 0 :(得分:1)

这不是这个问题的真正答案,但无论如何我会在这里发布,因为它可能对某人有帮助。

所以我需要做的就是在客户端处理一些东西(不在sw中),我通过使用MessageChannel来实现它,让sw和客户端进行双向通信。

我做了什么:

  1. 设置sw以侦听获取事件
  2. 在承诺中创建MessageChannel,让客户发送回复
  3. 使用MessageChannel
  4. 向客户端发送获取事件
  5. 客户 - 做点什么
  6. 将回复发送给sw女巫MessageChannel
  7. 你可以从这个谷歌的例子中得到基本的想法: https://googlechrome.github.io/samples/service-worker/post-message/

    最重要的部分是将工作委托给客户,让它在另一个端口上做出响应,将整个过程转变为这样的承诺:

    // 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);
    });
    

    如果您希望查看我的用例,可以使用here MessageClient来完成工作{/ 3}}

    随便提出问题,将很乐意回答