Javascript 在激活事件侦听器之前,异常不会被捕获
我正在使用的是抛出一个异常,该异常将不起作用。以下是片段:Javascript 在激活事件侦听器之前,异常不会被捕获,javascript,node.js,exception,mandrill,unhandled-exception,Javascript,Node.js,Exception,Mandrill,Unhandled Exception,我正在使用的是抛出一个异常,该异常将不起作用。以下是片段: 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
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\u client.templates.info
时调用的后续方法
调用的第一个方法是:
控件传递给
最后,抛出此错误的方法:
注:根据:
throw语句抛出用户定义的异常。当前函数的执行将停止(抛出后的语句将不被执行),并且控制将传递给调用堆栈中的第一个catch块。如果调用函数之间不存在catch块,程序将终止
但这并没有发生 原因是您在try…catch
块中执行的函数使用回调处理错误,并且在调用回调之前可能正在执行一些异步任务。Javascripttry…catch
仅适用于同步/阻止任务。原因是您在try…catch
块中执行的函数使用回调处理错误,并且可能在调用回调之前执行一些异步任务。Javascripttry…catch
仅适用于同步/阻塞任务。如果库异步抛出,那就是一个问题。除了编辑库之外,您无法以任何方式修复此问题。坏图书馆,坏图书馆
异步函数启动异步操作,然后返回,代码继续执行,直到调用堆栈清除为止(并且您的任何异常处理程序都消失)。然后,稍后,异步操作会触发回调(使用干净的调用堆栈),如果它在那里抛出异常,那么调用堆栈中就没有代码可以捕获它。该库负责捕获自己的异步异常,并以文档化的方式将它们传回调用方—通常通过回调中的错误参数(如您在标准nodejs库中看到的所有异步操作)
下面是一个例子来说明:
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");
如果库异步抛出,那就是一个问题。除了编辑库之外,您无法以任何方式修复此问题。坏图书馆,坏图书馆
异步函数启动异步操作,然后返回,代码继续执行,直到调用堆栈清除为止(并且您的任何异常处理程序都消失)。然后,稍后,异步操作会触发回调(使用干净的调用堆栈),如果它在那里抛出异常,那么调用堆栈中就没有代码可以捕获它。该库负责捕获自己的异步异常,并以文档化的方式将它们传回调用方—通常通过回调中的错误参数(如您在标准nodejs库中看到的所有异步操作)
下面是一个例子来说明:
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");
有道理。处理这个问题的方法是什么?不想编辑模块代码。对于同步错误处理,您可以使用ES2016async…wait
,或ES2015 Promissions。在这两种情况下,您都需要将回调转换为Promise
。另一个选项是在回调本身中使用try…catch
。您可以检查此项以供参考-有意义。处理这个问题的方法是什么?不想编辑模块代码。对于同步错误处理,您可以使用ES2016async…wait
,或ES2015 Promissions。在这两种情况下,您都需要将回调转换为Promise
。另一个选项是在回调本身中使用try…catch
。您可以对此进行检查以供参考-如果库异步抛出,这就是一个问题。除了编辑库之外,您无法以任何方式修复此问题。坏库,坏库。异步操作启动操作,然后返回,代码继续执行,直到调用堆栈清除(并且您的任何异常处理程序都消失)。然后,稍后,异步操作会触发回调(使用干净的调用堆栈),如果它在那里抛出异常,那么调用堆栈中就没有代码可以捕获它。库负责捕获自己的异步回调,并以文档化的方式将它们传回调用方—通常通过回调中的错误参数。@jfriend00。谢谢。如果库异步抛出,那就是一个问题。除了编辑库之外,您无法以任何方式修复此问题。坏库,坏库。异步操作启动操作,然后返回,代码继续执行,直到调用堆栈清除(并且您的任何异常处理程序都消失)。然后,稍后,异步操作会触发回调(使用干净的调用堆栈),如果它在那里抛出异常,那么调用堆栈中就没有代码可以捕获它。库负责捕获自己的异步回调,并以文档化的方式将它们传回调用方—通常通过回调中的错误参数。@jfriend00。谢谢你。@S