Why should a sampling request be cloned in a service?

In one example, Google Service Worker, 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; } ); }) ); }); 

On the other hand, the example provided by MDN, Using Service Workers , does not clone the request.

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

So, in case of a cache error in the Google example:

I understand why we should clone the answer: because cache.put consuming cache.put , and we still want to return the answer back to the web page that requested it.

But why do you need to clone a request? The comment says it is consumed by the cache and browser for retrieval . What does it mean?

  • Where is the request stream used in the cache? cache.put ? If so, why does caches.match not consume the request?
+8
javascript service-worker
source share
2 answers

The comment, it seems to me, clearly explains why the author of this code thought about cloning:

A request is a stream and can only be used once. Since we consume this once by the cache and once by the browser to retrieve, we need to clone the response.

Remember that the request body can be ReadableStream . If cache.match had to read the stream (or partially read the stream) to find out if the cache entry matches, the subsequent reading of fetch will continue, which will be read, there will be no data that cache.match read.

I would not be surprised if this mattered only in limited situations (if only the code in the Google example is simply not right, and this is not necessary), and therefore the inability to do this probably works in many test cases (for example, where the body is null or string, not stream). Remember that MDN is very good, but it is edited by the community, and errors and bad examples work periodically. (I had to fix a few glaring errors over the years.) Usually the community notices them and corrects them.

+2
source share

fetch are not cached and therefore caches essentially do not consume request

Therefore, there is no need to clone. - asked Jake about his writing earlier.

responses , however, put or added to the cache and / or can be passed along then as JSON / text / something else - which means that they / can be used.

My guess: if you use or mutate , then you need to clone it.

A read may not do in caches.match

I also suggest that maybe another reason is that reading on the request itself is not piped in the chain and only reading once as caches.match , as soon as this happens, reading happens only once, but the response flow may be transferred to other pipelines with mutation / conversion / recording

I just grab from the specification of flows ... also to decrypt everything that develops. Maybe I'll leave it to the experts

So, if I still rephrase my understanding, clone what is ideally consumed , and don't worry otherwise. And in this case, the read itself does not mutate the request / writes it elsewhere, so there is no need to clone

0
source share

All Articles