在激活事件监听器之前,异常未被捕获

时间:2017-08-31 06:48:39

标签: javascript node.js exception mandrill unhandled-exception

我正在使用的module正在抛出异常,这是未被捕获的。这是片段:

try {
    mandrill_client.templates.info({ name: 'plaintexttemplates' }, (r, e) => {

      console.log(e, 'e');


      console.log(r, 'r');
    });
} catch (e) {

    console.log('From trycatch', e); // NEVER CAUGHT!!
}

现在,当我运行时,会发生以下情况:

/home/suhail/test/node_modules/mandrill-api/mandrill.js:114
  throw {
  ^
Unknown_Template: No such template "plaintexttemplates"

这确实是一个未处理的异常(来自我正在使用的节点模块)。但为什么我的try/catch无法抓住这个?

为了捕获此异常,我激活了一个监听器:

process.on('uncaughtException', (err) => {
    console.log('ERRRR', err); // WORKS FINE, OBVIOUSLY!!
});

看起来我的概念不适合异常处理。谁能告诉我为什么try/catch无法捕捉异常?我错过了什么吗?

我没有在这里发布模块代码,但已经发布了下面代码函数的引用。这是我在调试过程中看到的流量控制。 以下是调用mandrill_client.templates.info时调用的后续方法。

第一个叫做的方法是: Templates.prototype.info

控件转到 Mandrill.prototype.call

最后抛出此错误的方法:Mandrill.prototype.onerror

PS:根据documentation: throw语句抛出用户定义的异常。当前函数的执行将停止(抛出后的语句将被执行)和control will be passed to the first catch block in the call stack。如果调用函数之间不存在catch块,则程序将终止。

但这不会发生!

2 个答案:

答案 0 :(得分:1)

原因是您在try...catch块中执行的函数使用回调处理错误,并且在调用回调之前可能正在执行一些异步任务。 Javascript try...catch仅适用于同步/阻止任务。

答案 1 :(得分:1)

如果库是异步投掷的,那就是一个问题。除了编辑库之外,您无法以任何方式解决此问题。坏图书馆,坏图书馆。

异步函数启动异步操作,然后返回并继续执行代码,直到调用堆栈清除(并且您的任何异常处理程序都消失了)。然后,稍后,异步操作会触发回调(带有一个干净的调用堆栈),如果它在那里抛出异常,则调用堆栈中没有任何代码可以捕获它。库有责任捕获自己的异步异常,并以文档化的方式将它们传回给调用者 - 通常通过回调中的错误参数(就像您在标准nodejs库中看到的所有异步操作一样)。 p>

以下是一个例子来说明:

function delay(t, callback) {
   setTimeout(function() {
       throw new Error("try to catch me");
       callback();    // won't get here
   }, t);
}

try {
   delay(100, function() {
       console.log("won't get here");
   });
} catch(e) {
   console.log("won't find any exception here");
}

console.log("will get here before the exception is thrown");

// exception will be thrown sometime later with a clean callstack so
// the above try/catch is no longer in place

处理这个问题的正确方法是让异步操作捕获它自己的异常并通过回调将它们传回:

function delay(t, callback) {
   setTimeout(function() {
       // async operation catches its own exceptions
       try {
           throw new Error("try to catch me");
           callback(null);    // won't get here
       } catch(e) {
           callback(e);
       }
   }, t);
}

delay(100, function(err) {
    if (err) {
        console.log(err);
    } else {
        console.log("got here with no error");
    }
});

console.log("will get here before the exception is thrown");
相关问题