即使处理了未捕获的异常,Node.js程序也会退出

时间:2019-06-27 11:02:49

标签: javascript node.js exception

我编写了以下代码来处理应用程序中未捕获的异常(我知道这是一个相当幼稚的错误处理方法,该代码仅用于解决问题):

process.on("uncaughtException", err => {
    console.log('Handling exception');
});

console.log('starting...');

function f() {
    throw(new Error('Error'));
}

f();
console.log('Done');

运行代码时,得到以下输出:

starting...
Handling exception

由于某种原因,即使处理了异常,该程序也没有运行最后一行代码就退出了。 当我使用一个f()块将对try-catch的调用包装起来时,执行的最后一行将'Done'字样打印到屏幕上。

我的问题是:

  1. 这是预期的行为吗?
  2. 为什么这两种机制(监听事件和使用try-catch)之间有区别?

1 个答案:

答案 0 :(得分:1)

这正是您所期望的行为,未捕获的异常将停止脚本的正常执行,因此将永远不会进行“完成”日志调用。

您可以在{.3}}上的Node.js文档中看到一个更好的例子。

如文档所述:

Note that 'uncaughtException' is a crude mechanism for exception handling intended to be used only as a last resort.

他们明确记录“这将无法运行”,因为这是预期的行为。

如果确实捕获到异常,脚本执行将不会停止,并且日志调用将照常进行。

process.on('uncaughtException', (err, origin) => {
  fs.writeSync(
    process.stderr.fd,
    `Caught exception: ${err}\n` +
    `Exception origin: ${origin}`
  );
});

setTimeout(() => {
  console.log('This will still run.');
}, 500);

// Intentionally cause an exception, but don't catch it.
nonexistentFunc();
console.log('This will not run.');

uncaughtException处理程序旨在做到这一点:在您自己的代码中捕获try ... catch处理程序未处理的所有异常。主要目的应该是记录错误,以便以后可以修复它们。

无论如何,最好将脚本包装在重启机制(如Forever)中,或者在发生这种情况时仅旋转一个新的Docker容器。

现在,在您的情况下,此脚本没有任何实际区别,因为该脚本将立即退出。但是请看一下这两个脚本之间的区别:

脚本1:

// Keep the script alive by setting a timeout. Because we have an exception handler in place we can keep doing stuff!
let interval = setInterval(() => console.log("I'm still alive!!"), 500);
setTimeout(() => { clearInterval(interval); console.log("Timeout done...")} , 5000);

process.on("uncaughtException", err => {
    console.log('Handling exception');
});

console.log('starting...');

function f() {
    throw(new Error('Error'));
}

f();

console.log('Done');

脚本2:

// Keep the script alive by setting a timeout. Since there is no exception handler set the script will terminate immediately in any case.

let interval = setInterval(() => console.log("I'm still alive!!"), 500);
setTimeout(() => { clearInterval(interval); console.log("Timeout done...")} , 5000);

console.log('starting...');

function f() {
    throw(new Error('Error'));
}

f();

console.log('Done');

由于第二个脚本中没有未捕获的异常处理程序,因此您可以立即退出。