From 0932bf9b9f6ab7f3f6940b8166c9d316326ccbec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=27rysiek=27=20Wo=C5=BAniak?= Date: Wed, 28 Feb 2024 06:47:02 +0000 Subject: [PATCH] exceptions thrown in plugins are now properly caught in libresilientFetch (ref. #36) --- service-worker.js | 89 +++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 41 deletions(-) diff --git a/service-worker.js b/service-worker.js index 35f98bc..c4fccb1 100644 --- a/service-worker.js +++ b/service-worker.js @@ -1026,48 +1026,55 @@ let initFromRequest = (req) => { * reqInfo - instance of LibResilientResourceInfo */ let libresilientFetch = (plugin, url, init, reqInfo) => { - // status of the plugin - reqInfo.update({ - method: (plugin && "name" in plugin) ? plugin.name : "unknown", - state: "running" - }) - - // log stuff - self.log('service-worker', "LibResilient Service Worker handling URL:", url, - '\n+-- init:', Object.getOwnPropertyNames(init).map(p=>`\n - ${p}: ${init[p]}`).join(''), - '\n+-- using method(s):', plugin.name - ) - - // starting the fetch... - // if it errors out immediately, at least we don't have to deal - // with a dangling promise timeout, set up below - let fetch_promise = plugin.fetch(url, init) - - let timeout_promise, timeout_id - [timeout_promise, timeout_id] = promiseTimeout( - self.LibResilientConfig.defaultPluginTimeout, - false, - `LibResilient request using ${plugin.name} timed out after ${self.LibResilientConfig.defaultPluginTimeout}ms.` - ) - - // making sure there are no dangling promises etc - // - // this has to happen asynchronously - fetch_promise - // make sure the timeout is cancelled as soon as the promise resolves - // we do not want any dangling promises/timeouts after all! - .finally(()=>{ - clearTimeout(timeout_id) + // we really need to catch any exceptions here + // otherwise other plugins will not run! + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch#gotchas_when_throwing_errors + try { + // status of the plugin + reqInfo.update({ + method: (plugin && "name" in plugin) ? plugin.name : "unknown", + state: "running" }) - // no-op to make sure we don't end up with dangling rejected premises - .catch((e)=>{}) - - // race the plugin(s) vs. the timeout - return Promise - .race([ - fetch_promise, - timeout_promise - ]); + + // log stuff + self.log('service-worker', "LibResilient Service Worker handling URL:", url, + '\n+-- init:', Object.getOwnPropertyNames(init).map(p=>`\n - ${p}: ${init[p]}`).join(''), + '\n+-- using method(s):', plugin.name + ) + + // starting the fetch... + // if it errors out immediately, at least we don't have to deal + // with a dangling promise timeout, set up below + let fetch_promise = plugin.fetch(url, init) + + let timeout_promise, timeout_id + [timeout_promise, timeout_id] = promiseTimeout( + self.LibResilientConfig.defaultPluginTimeout, + false, + `LibResilient request using ${plugin.name} timed out after ${self.LibResilientConfig.defaultPluginTimeout}ms.` + ) + + // making sure there are no dangling promises etc + // + // this has to happen asynchronously + fetch_promise + // make sure the timeout is cancelled as soon as the promise resolves + // we do not want any dangling promises/timeouts after all! + .finally(()=>{ + clearTimeout(timeout_id) + }) + // no-op to make sure we don't end up with dangling rejected premises + .catch((e)=>{}) + + // race the plugin(s) vs. the timeout + return Promise + .race([ + fetch_promise, + timeout_promise + ]); + } catch(e) { + return Promise.reject(e) + } }