fix(service-worker): cache opaque responses when requests exceeds timeout threshold (#30977)
PR Close #30977
This commit is contained in:
parent
d7be38f84b
commit
93abc35213
|
@ -378,7 +378,7 @@ export class DataGroup {
|
||||||
|
|
||||||
// If the network fetch times out or errors, fall back on the cache.
|
// If the network fetch times out or errors, fall back on the cache.
|
||||||
if (res === undefined) {
|
if (res === undefined) {
|
||||||
ctx.waitUntil(this.safeCacheResponse(req, networkFetch));
|
ctx.waitUntil(this.safeCacheResponse(req, networkFetch, true));
|
||||||
|
|
||||||
// Ignore the age, the network response will be cached anyway due to the
|
// Ignore the age, the network response will be cached anyway due to the
|
||||||
// behavior of freshness.
|
// behavior of freshness.
|
||||||
|
@ -434,9 +434,10 @@ export class DataGroup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async safeCacheResponse(req: Request, res: Promise<Response>): Promise<void> {
|
private async safeCacheResponse(req: Request, res: Promise<Response>, okToCacheOpaque?: boolean):
|
||||||
|
Promise<void> {
|
||||||
try {
|
try {
|
||||||
await this.cacheResponse(req, await res, await this.lru());
|
await this.cacheResponse(req, await res, await this.lru(), okToCacheOpaque);
|
||||||
} catch {
|
} catch {
|
||||||
// TODO: handle this error somehow?
|
// TODO: handle this error somehow?
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,6 +259,36 @@ import {SwTestHarness, SwTestHarnessBuilder} from '../testing/scope';
|
||||||
expect(await makeRequest(scope, '/refresh/data')).toEqual('this is refreshed data');
|
expect(await makeRequest(scope, '/refresh/data')).toEqual('this is refreshed data');
|
||||||
serverUpdate.assertNoOtherRequests();
|
serverUpdate.assertNoOtherRequests();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('caches opaque responses on refresh', async() => {
|
||||||
|
// Make the initial request and populate the cache.
|
||||||
|
expect(await makeRequest(scope, '/fresh/data')).toBe('this is fresh data');
|
||||||
|
server.assertSawRequestFor('/fresh/data');
|
||||||
|
server.clearRequests();
|
||||||
|
|
||||||
|
// Update the server state and pause the server, so the next request times out.
|
||||||
|
scope.updateServerState(serverUpdate);
|
||||||
|
serverUpdate.pause();
|
||||||
|
const [res, done] =
|
||||||
|
makePendingRequest(scope, new MockRequest('/fresh/data', {mode: 'no-cors'}));
|
||||||
|
|
||||||
|
// The network request times out after 1,000ms and the cached response is returned.
|
||||||
|
await serverUpdate.nextRequest;
|
||||||
|
scope.advance(2000);
|
||||||
|
expect(await res).toBe('this is fresh data');
|
||||||
|
|
||||||
|
// Unpause the server to allow the network request to complete and be cached.
|
||||||
|
serverUpdate.unpause();
|
||||||
|
await done;
|
||||||
|
|
||||||
|
// Pause the server to force the cached (opaque) response to be returned.
|
||||||
|
serverUpdate.pause();
|
||||||
|
const [res2] = makePendingRequest(scope, '/fresh/data');
|
||||||
|
await serverUpdate.nextRequest;
|
||||||
|
scope.advance(2000);
|
||||||
|
|
||||||
|
expect(await res2).toBe('');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
Loading…
Reference in New Issue