如何汇总 JavaScript 错误

How to roll up a JavaScript error?

本文关键字:错误 JavaScript 何汇总      更新时间:2023-09-26

在下面的代码中,我故意抛出了一个错误,但在 Chrome(仅用于测试目的)中,它不会汇总到捕获。如何将错误汇总到父级的范围中?

try {
  setTimeout(function() {
    console.log("Throwing Error...");
    throw({message:"Ouch!"});
  }, 500);
} catch(e) {
  console.log(e.message);
}

Chrome 回复:

Uncaught #<Object>
  (anonymous function)

这是我正在使用的完整示例;当我需要"bob"时,它(故意)超时。我想捕获 requirejs 错误,以便我可以使用我的应用程序的错误系统(更健壮)来通知学习者。

(function() {
try {
  var scriptVersion = "1.0.0.1"
  window.onload = function() {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = "//content.com/pkg/" + scriptVersion + "/require-jquery.js";
    script.async = false;
    script.done = false;
    // OnReadyStateChange for older IE browsers
    script.onload = script.onreadystatechange = function() {
      if(!(this.done) && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete")) {
        this.done = true;
        require.config({
          baseUrl: "//content.com/pkg/" + scriptVersion
        });
        require(["bob"]);
      }
    }
    document.getElementsByTagName("head")[0].appendChild(script);
  }
} catch(e) {
  console.log(e);
}
})();

请参阅下面的编辑,了解如何使用 requireJS 解决实际问题。

问题是 setTimeout() 函数在父级的作用域中运行并且完成时没有错误。 它(与系统一起)调度一个未来的回调事件,但是当该回调在未来发生时,父级的执行范围已经完成,并且回调从顶层的系统启动,就像新的系统事件(例如 click 事件处理程序)一样。

虽然父闭包仍然存在,因为setTimeout()内的匿名函数仍然可以引用这些变量,但父作用域的实际执行已完成,因此 try/catch 的作用域已完成。

setTimeout()匿名函数的执行上下文是顶级的(由系统启动),因此没有可以放入 try/catch 的父上下文。 您可以在匿名函数中放置一个 try/catch,但从那里抛出只会回到系统,这就是所谓的setTimeout()回调。

要让你自己的代码捕获setTimeout()回调中发生的任何异常,你需要在回调中放置一个 try/catch。

  setTimeout(function() {
    try {
        console.log("Throwing Error...");
        throw({message:"Ouch!"});
    } catch(e) {
        console.log(e.message);
    }
  }, 500);

如果您解释了您尝试解决的真正问题是什么(而不是这个制造的测试用例),我们也许能够提供一些有用的选项。


现在编辑,您已经展示了您真正要解决的问题。 require.js 库通过调用 onError 方法来启动每个错误。 onError方法的默认实现是引发异常的原因。 您可以分配自己的onError处理程序,并在回调中处理错误,而不是处理异常。 这听起来是正确的方法。

从 requirejs 源:

/**
 * Any errors that require explicitly generates will be passed to this
 * function. Intercept/override it if you want custom error handling.
 * @param {Error} err the error object.
 */
req.onError = function (err) {
    throw err;
};

您的throw发生在catch块之后的一段时间,当浏览器调用setTimeout回调时。

catch使用逻辑范围,而不是词法范围)

前面的回答者解释得对。

另一种思考方式是它不起作用,因为 setTimeout 完成得很好,并且在最初运行时不会抛出和异常。然后,当您不再位于 try-catch 块中时,它会稍后执行。

如果您将 try catch 放在 setTimeout 函数中,它将起作用,如下所示:

  setTimeout(function() {
     try {
         console.log("Throwing Error...");
         throw({message:"Ouch!"});
     } catch(e) {
       console.log(e.message);
     }
      }, 500);

如果您仍有疑问,请告诉我。

像这样使用包装函数。

// wrapper function
var tryable = function(closure, catchCallback) {
    closure(function(callback) {
        return function() {
            try {
                callback();
            } catch(e) {
                catchCallback(e);
            }
        };
    });
};

function throwException() {
    throw new Error("Hi");
}
tryable(function(catchable) {
    setTimeout(catchable(throwException), 1000);
}, function(e) {
    console.log("Error:)", e);
});