3

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

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

Chrome 回复:

Uncaught #<Object>
  (anonymous function)

这是我正在使用的完整示例;当我需要“鲍勃”时,它(故意)超时。我想捕获 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);
}
})();
4

4 回答 4

6

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

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

虽然父闭包仍然存在,因为内部的匿名函数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;
};
于 2012-04-26T16:08:11.740 回答
1

前面的回答者解释正确。

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

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

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

如果您还有问题,请告诉我。

于 2012-04-26T16:11:16.423 回答
1

当浏览器调用回调时,您会在块throw之后的某个时间发生。catchsetTimeout

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

于 2012-04-26T16:04:16.497 回答
1

像这样使用包装函数。

// 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);
});
于 2015-03-09T07:49:40.373 回答