跳转至

Promise

UnhandledPromiseRejectionWarning

如果 Promise 运行过程中抛出错误,或者状态变为rejected,但是没有相应的处理代码,那么 Node 会抛出一个警告UnhandledPromiseRejectionWarning

new Promise(function (resolve, reject) {
  reject('message');
  console.log('hello');
})
// hello
// UnhandledPromiseRejectionWarning: message

上面代码中,Promise 变为rejected状态,但是没有处理的代码,导致抛出警告UnhandledPromiseRejectionWarning。由于抛出的是警告,而不是错误,所以不影响hello的输出。请跟下面的代码比较一下。

new Promise(function (resolve, reject) {
  throw new Error('message');
  console.log('hello');
})
// UnhandledPromiseRejectionWarning: Error: message

上面代码中,Promise 内部抛出错误,没有得到处理,所以会有警告UnhandledPromiseRejectionWarning。Promise 内部的错误阻止 Promise 内部的代码继续向下运行,所以不会输出hello

消除这个警告的方法很简单,就是为 Promise 加上错误处理代码,即catch代码块。

new Promise(function (resolve, reject) {
  reject('message');
  console.log('hello');
}).catch(function (err) { console.log (err) })
// hello
// message

上面代码中,由于catch代码块的存在,所以不会抛出警告。

async 函数里面使用 Promise,也要放在try/catch代码块之中。

const p = new Promise(function (resolve, reject) {
  reject('message');
});

(async function () {
  try {
    await p;
  } catch (err) {
    console.log(err);
  }
})();
// message

上面代码中,如果 Promise 没有放在try/catch代码块,就会抛出警告UnhandledPromiseRejectionWarning

Node 还提供process对象的unhandledRejection事件,在抛出警告UnhandledPromiseRejectionWarning之前,就会触发这个事件。如果设置了这个事件的处理代码,就不会抛出警告UnhandledPromiseRejectionWarning

new Promise(function (resolve, reject) {
  reject('message');
});

process.on('unhandledRejection', function (err) {
  console.log(err);
});
// message

Node 开发团队打算废除UnhandledPromiseRejectionWarning,以后如果没有相应的处理代码,Promise 内部抛错或者变为rejected状态,会导致 Node 进程终止执行,并且有一个非零的返回码。所以应该养成习惯,只要有 Promise,就要部署失败情况下的代码。