为什么必须在 Service Worker 中克隆 fetch 请求? [英] Why does fetch request have to be cloned in service worker?

查看:62
本文介绍了为什么必须在 Service Worker 中克隆 fetch 请求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Google 的一个 Service Worker 示例中,缓存和退货请求

In one of the Service Worker examples by Google, cache and return requests

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        // Cache hit - return response
        if (response) {
          return response;
        }

        // IMPORTANT: Clone the request. A request is a stream and
        // can only be consumed once. Since we are consuming this
        // once by cache and once by the browser for fetch, we need
        // to clone the response.
        var fetchRequest = event.request.clone();

        return fetch(fetchRequest).then(
          function(response) {
            // Check if we received a valid response
            if(!response || response.status !== 200 || response.type !== 'basic') {
              return response;
            }

            // IMPORTANT: Clone the response. A response is a stream
            // and because we want the browser to consume the response
            // as well as the cache consuming the response, we need
            // to clone it so we have two streams.
            var responseToCache = response.clone();

            caches.open(CACHE_NAME)
              .then(function(cache) {
                cache.put(event.request, responseToCache);
              });

            return response;
          }
        );
      })
    );
});

<小时>

另一方面,MDN提供的例子,使用Service Workers,不会克隆请求.

this.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request).then(function(resp) {
      return resp || fetch(event.request).then(function(response) {
        caches.open('v1').then(function(cache) {
          cache.put(event.request, response.clone());
        });
        return response;
      });
    }).catch(function() {
      return caches.match('/sw-test/gallery/myLittleVader.jpg');
    })
  );
});

<小时>

因此在 Google 示例中缓存未命中的情况下:


So in the case of a cache miss in the Google example:

我理解为什么我们必须克隆响应:因为它被 cache.put 使用,我们仍然希望将响应返回给请求它的网页.

I understand why we have to clone the response: because it's consumed by cache.put, and we still want to return the response back to the webpage who requested it.

但是为什么要克隆请求呢?在评论中,它说它被缓存浏览器用于获取.它到底是什么意思?

But why does one have to clone the request? In the comment it says it's consumed by cache and the browser for fetch. What does it mean exactly?

  • 请求流消耗在缓存中的哪个位置?cache.put?如果是这样,为什么 caches.match 不使用请求?
  • Where in the cache is the request stream consumed? cache.put? If so, why doesn't caches.match consume the request?

推荐答案

在我看来,评论很清楚地说明了为什么该代码的作者认为克隆是必要的:

The comment seems to me to say quite clearly why the author of that code thought cloning was necessary:

一个请求是一个流,只能被消费一次.由于我们一次通过缓存使用它,一次由浏览器用于获取,因此我们需要克隆响应.

A request is a stream and can only be consumed once. Since we are consuming this once by cache and once by the browser for fetch, we need to clone the response.

记住请求的body可以是 ReadableStream.如果 cache.match 必须读取流(或部分读取流)才能知道缓存条目是否匹配,则 fetch 的后续读取将继续读取,缺少 cache.match 读取的任何数据.

Remember that the body of a request can be a ReadableStream. If cache.match had to read the stream (or partially read the stream) to know whether a cache entry was a match, a subsequent read by fetch would continue that read, missing any data that cache.match read.

如果它只在有限的情况下重要(除非 Google 示例中的代码完全错误并且没有必要),我不会感到惊讶,因此如果不这样做可能在许多测试用例中都有效(例如,其中主体是 null 或字符串,而不是流).请记住,MDN 非常好,但它 是社区编辑的,错误和糟糕的示例确实会定期出现.(多年来,我不得不修复其中的几个明显错误.)通常社区会发现并修复它们.

I wouldn't be surprised if it only mattered in limited situations (unless the code in the Google example is just plain wrong and it's not necessary), and so failing to do it probably works in many test cases (for instance, where the body is null or a string, not a stream). Remember that MDN is very good, but it is community-edited, and errors and poor examples do creep in periodically. (I've had to fix several blatant errors in it over the years.) Usually the community spots them and fixes them.

这篇关于为什么必须在 Service Worker 中克隆 fetch 请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆