I have this code in my Service Worker:
self.addEventListener('fetch', (event) => {
event.respondWith(new Promise(async (resolve, reject) => {
const req = event.request;
try {
const res = new HTTPResponse(resolve, reject);
await chain_handlers(this._middlewares, function(fn, next) {
return fn(req, res, next);
});
const method = req.method;
const url = new URL(req.url);
const path = normalize_url(url.pathname);
const routes = this._routes[method];
if (routes) {
const match = this._parser.pick(routes, path);
if (match.length) {
const [first_match] = match;
const fns = [...this._middlewares, ...routes[first_match.pattern]];
req.params = first_match.data;
setTimeout(function() {
reject('Timeout Error');
}, this._timeout);
await chain_handlers(fns, (fn, next) => {
return fn(req, res, next);
});
return;
}
}
if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') {
return;
}
//request = credentials: 'include'
fetch(event.request).then(resolve).catch(reject);
} catch(error) {
this._handle_error(resolve, req, error);
}
}));
});
And I’ve noticed that when the JS file is blocked by AdBlocker (uBlock) Chrome Extension I’ve got an error with a stack trace in dev tools:
The errors came from Analytics (OWA) that I have on my blog.
So the question is what is the purpose of reject
in a fetch
event? And how to properly handle Errors like this in service Workers to not get a stack trace?
EDIT: I’ve needed to put my whole code of the fetch even because got a lot of comments about async/await and Promise constructor, and it’s not feasible to use one without the other in my case.
This doesn’t changes the question.
EDIT2:
So I’ve minimized the code, this is my real question I don’t care that I have anti-pattern a lot of libraries do things that you don’t normally do I don’t care. I just want to get the answer to this simple question:
How to don’t get a stack trace and how and what is rejection in Promise for fetch event for? How to properly handle fetch rejection in a Service Worker fetch event?
This is simplified code:
self.addEventListener('fetch', (event) => {
event.respondWith(new Promise((resolve, reject) => {
fetch(event.request).then(resolve).catch(reject);
}));
});
self.addEventListener('activate', (event) => {
event.waitUntil(clients.claim());
});
And this is the console when AdBlock is on:
2
Answers
This is not intuitive but you need to catch and ignore the promise rejection when using the Promise constructor:
You will still get an error in the console. This is the console output:
As you can see from the above screenshot there are no stack traces but the error about blocking the request is still there.
It appears the unhandled rejection is a problem with Chrome’s
respondWith
implementation. It does handle both fulfillment and rejection of the argument promise, so it should not leave the rejected promise marked as unhandled.You can work around this by handling (by ignoring) the rejection of the promise before passing it to
respondWith
: