Skip to content

Commit 4c42e74

Browse files
committed
Make pending fetches promise code more robust
There was a slight possibility that two requests on a given URL running in parallel could create two separate promises (and run two requests instead of one).
1 parent 271aede commit 4c42e74

File tree

1 file changed

+19
-14
lines changed

1 file changed

+19
-14
lines changed

fetch-filecache.js

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -254,13 +254,17 @@ async function fetch(url, options) {
254254
}
255255
}
256256

257-
async function getPendingFetch() {
257+
function isFetchPending() {
258+
return !!pendingFetches[url];
259+
}
260+
261+
async function pendingFetchIsOver() {
258262
if (pendingFetches[url]) {
259263
log('wait for pending request');
260-
return pendingFetches[url].promise;
264+
await pendingFetches[url].promise;
261265
}
262266
else {
263-
return false;
267+
throw new Error('There was no pending request');
264268
}
265269
}
266270

@@ -269,7 +273,7 @@ async function fetch(url, options) {
269273
* the code may resolve or reject it through calls to resolvePendingFetch and
270274
* rejectPendingFetch functions
271275
*/
272-
function addPendingFetch(url) {
276+
function addPendingFetch() {
273277
let resolve = null;
274278
let reject = null;
275279
let promise = new Promise((innerResolve, innerReject) => {
@@ -284,13 +288,13 @@ async function fetch(url, options) {
284288
promise.catch(err => {});
285289
}
286290

287-
function resolvePendingFetch(url) {
291+
function resolvePendingFetch() {
288292
if (!pendingFetches[url]) return;
289293
pendingFetches[url].resolve(true);
290294
delete pendingFetches[url];
291295
}
292296

293-
function rejectPendingFetch(url, err) {
297+
function rejectPendingFetch(err) {
294298
if (!pendingFetches[url]) return;
295299
pendingFetches[url].reject(err);
296300
delete pendingFetches[url];
@@ -396,30 +400,31 @@ async function fetch(url, options) {
396400

397401
log('fetch ' + url);
398402
await checkCacheFolder();
399-
let pendingFetchWasOngoing = await getPendingFetch();
400-
if (pendingFetchWasOngoing) {
401-
// There was a pending fetch, reuse the cached answer
402-
// (NB: we would not be able to reuse the Response object directly because
403+
if (isFetchPending()) {
404+
// There is a pending fetch, wait for that fetch to finish and reuse the
405+
// cached answer (NB: we cannot reuse the Response object directly because
403406
// response body stream can only be read once)
407+
let pendingFetch = await pendingFetchIsOver();
408+
404409
log('pending request over, return response from cache');
405410
return readFromCache();
406411
}
407412
else {
408-
addPendingFetch(url);
413+
addPendingFetch();
409414
try {
410415
let headers = await readHeadersFromCache();
411416
if (hasExpired(headers, config.refresh)) {
412417
let response = await conditionalFetch(headers);
413-
resolvePendingFetch(url);
418+
resolvePendingFetch();
414419
return response;
415420
}
416421
else {
417-
resolvePendingFetch(url, 'test');
422+
resolvePendingFetch();
418423
return readFromCache();
419424
}
420425
}
421426
catch (err) {
422-
rejectPendingFetch(url, err);
427+
rejectPendingFetch(err);
423428
throw err;
424429
}
425430
}

0 commit comments

Comments
 (0)