2

unlike what one may expect, the following code will not trigger the window.error handler

window.addEventListener("error",function(error){
    alert("uncaught error somewhere!");
});

(async function(){
let foo= ((await ( await fetch("/no_json_plz_i_want_an_error")).json()));
})();

(reason being "because the error occurs in a promise context" according to a comment on this question: why doesn't fetch().json() errors trigger window.onerror? )

what is the correct way to explicitly propagate it to the window error handler? this doesn't work either, for some reason it still doesn't propagate to window.error:

(async function(){
let foo= ((await ( await fetch("/no_json_plz_i_want_an_error")).json()));
})().catch(function(err){
    throw err;
});

this doesn't seem to work either (why? no idea)

(async function(){
let foo= ((await ( await fetch("/no_json_plz_i_want_an_error")).json()));
})().catch(function(err){
    let ev = new ErrorEvent(err.message, err);
    window.dispatchEvent(ev);
});

and this approach fails with the error Uncaught (in promise) DOMException: Failed to execute 'dispatchEvent' on 'EventTarget': The event provided is uninitialized., whatever that means

(async function(){
let foo= ((await ( await fetch("/no_json_plz_i_want_an_error")).json()));
})().catch(function(err){
  let ev= document.createEvent("ErrorEvent");
  ev.error=err;
  window.dispatchEvent(ev);
});

so.. what is the correct way to do it?

hanshenrik
  • 19,904
  • 4
  • 43
  • 89

1 Answers1

4

You can use unhandledrejection event to catch the promises error in window object instead.

Edit:

As fetch() will still return response object and there is no error throwing. You can throw a error when the response.ok is false. See function run1 below:

The run2 function will throw a JSON token error as the response.ok is false and it tries to parse the data.

You may try to run in your local environment because fiddle may wrap the error handling in the console.

window.addEventListener("unhandledrejection", function (e) {
  console.log("Error occurred: " + e.reason.message);
});

(async function run1() {
  try {
    let response = await fetch("/no_json_plz_i_want_an_error");
    if (response.ok) {
      const data = response.json();
    } else {
      throw new Error("Unable to fetch()");
    }
  } catch (err) {
    throw new Error(err);
  }
})();

(async function run2() {
  try {
    await (await fetch("/no_json_plz_i_want_an_error")).json();
  } catch (err) {
    throw new Error(err);
  }
})();
ikhvjs
  • 5,316
  • 2
  • 13
  • 36
  • sounds great! unfortunately i can't get that handler invoked either on jsfiddle: https://jsfiddle.net/hqs6om2p/2/ – hanshenrik Aug 05 '21 at 11:06
  • @hanshenrik, I updated my answer. I hope it makes more sense to you. – ikhvjs Aug 05 '21 at 12:06
  • oh sorry, this has been confusing me while testing your code, https://stackoverflow.com/questions/68681822/unhandledrejection-handler-invoked-on-firefox-but-not-on-chrome – hanshenrik Aug 06 '21 at 12:51
  • 1
    there's a chance your catch+throw approach is only required for Chrome-browsers because of [a bug in Chrome](https://bugs.chromium.org/p/chromium/issues/detail?id=1219363&q=unhandledrejection&can=2) , ie it's not required on Firefox – hanshenrik Aug 06 '21 at 13:03