- From: Joshua Bell <notifications@github.com>
- Date: Fri, 19 Feb 2016 15:30:43 -0800
- To: slightlyoff/ServiceWorker <ServiceWorker@noreply.github.com>
- Message-ID: <slightlyoff/ServiceWorker/issues/836/186450287@github.com>
The best I could come up with that approximates the original desired semantics - multiple cooperating handlers asynchronously decide if they are the one that will service the request, and have unfettered access to the `fetch` event - is something like the following. Like @mkruisselbrink I'm relying on the fact that multiple handlers see the same `Event` object and can decorate it.
```js
function Helper(event) {
var promises = [], count = 0, resolve;
this.response = new Promise(r => resolve = r);
this.add = function(p) {
p.then(
r => resolve(r),
() => {
if (++count === promises.length)
resolve(fetch(event.request));
});
};
}
// Multiple of these allowed
self.addEventListener('fetch', event => {
if (!event.helper) event.helper = new Helper(event);
event.helper.add(new Promise((resolve, reject) => {
self.caches.match(event.request).then(response => {
if (response)
resolve(response);
else
reject();
}).catch(reject);
}));
event.respondWith(event.helper.response);
});
```
I believe this has a race, though: if the first handler's cache check resolves before the second event handler is run, the Helper will conclude all associated Promises have completed. That could be addressed with a `setTimeout(..., 0)`, or maybe we can't run microtasks during event dispatch and it's moot.
That's an awful lot of boilerplate per handler, though. So I agree that middleware is probably cleanest. If the handlers add Request → Promise<Response> functions to a collection (`self.fetchHandlers`, say) then the actual fetch handler can "race" them all, ignoring ones that reject. If all reject, it falls back to `fetch(event.request)`
---
Reply to this email directly or view it on GitHub:
https://github.com/slightlyoff/ServiceWorker/issues/836#issuecomment-186450287
Received on Friday, 19 February 2016 23:31:11 UTC