如何将 Promise 上下文中未捕获的错误传播到 window.onerror?

han*_*rik 2 javascript error-handling promise

与人们想象的不同,以下代码不会触发 window.error 处理程序

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

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

Run Code Online (Sandbox Code Playgroud)

(根据对此问题的评论,原因是“因为错误发生在承诺上下文中”:why does not fetch().json()Errors trigger window.onerror?

将其显式传播到窗口错误处理程序的正确方法是什么?这也不起作用,由于某种原因它仍然不会传播到 window.error:

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

这似乎也不起作用(为什么?不知道)

(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);
});
Run Code Online (Sandbox Code Playgroud)

这种方法失败并出现错误Uncaught (in promise) DOMException: Failed to execute 'dispatchEvent' on 'EventTarget': The event provided is uninitialized.,无论这意味着什么

(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);
});
Run Code Online (Sandbox Code Playgroud)

那么..正确的做法是什么?

ikh*_*vjs 5

您可以使用unhandledrejection事件来捕获窗口对象中的承诺错误。

编辑:

因为 fetch() 仍然会返回响应对象并且不会抛出错误。当为 false 时,您可以抛出错误response.ok。参见下面的函数run1

run2函数将抛出一个 JSON 令牌错误,因为它response.ok是 false,并且它会尝试解析数据。

您可以尝试在本地环境中运行,因为 fiddle 可能会将错误处理包装在控制台中。

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);
  }
})();
Run Code Online (Sandbox Code Playgroud)