什么是未处理的承诺拒绝?

问题描述 投票:137回答:5

为了学习Angular 2,我正在尝试他们的教程。

我收到这样的错误:

(node:4796) UnhandledPromiseRejectionWarning: Unhandled promise rejection (r                                                                                                     ejection id: 1): Error: spawn cmd ENOENT
[1] (node:4796) DeprecationWarning: Unhandled promise rejections are deprecated.
In the future, promise rejections that are not handled will terminate the Node.
js process with a non-zero exit code.

我在SO中经历了不同的问题和答案,但无法找出“未处理的承诺拒绝”是什么。

任何人都可以简单地解释一下它是什么以及Error: spawn cmd ENOENT是什么,什么时候出现以及我必须检查以摆脱这个警告?

javascript angular es6-promise spawn unhandled-exception
5个回答
150
投票

这个错误的根源在于,每个承诺都应该处理承诺拒绝,即具有.catch(...)。您可以通过在代码中的promise中添加.catch(...)来避免相同的操作,如下所示。

例如,函数PTest()将根据全局变量some​​var的值来解析或拒绝promise

var somevar = false;
var PTest = function () {
    return new Promise(function (resolve, reject) {
        if (somevar === true)
            resolve();
        else
            reject();
    });
}
var myfunc = PTest();
myfunc.then(function () {
     console.log("Promise Resolved");
}).catch(function () {
     console.log("Promise Rejected");
});

在某些情况下,即使我们为promises编写了.catch(..),也会出现“未处理的promise promise”消息。这都是关于你如何编写代码的。即使我们正在处理catch,以下代码也会生成“未处理的承诺拒绝”。

var somevar = false;
var PTest = function () {
    return new Promise(function (resolve, reject) {
        if (somevar === true)
            resolve();
        else
            reject();
    });
}
var myfunc = PTest();
myfunc.then(function () {
     console.log("Promise Resolved");
});
// See the Difference here
myfunc.catch(function () {
     console.log("Promise Rejected");
});

不同之处在于,您不将.catch(...)作为链条处理,而是将其作为单独处理。出于某种原因,JavaScript引擎将其视为承诺而没有未处理的承诺拒绝。


30
投票

这是当Promise.reject()完成或者在async执行的代码中抛出异常并且.catch()没有处理拒绝时。

被拒绝的承诺就像是一个异常,它向应用程序入口点冒泡并导致根错误处理程序产生该输出。

也可以看看


20
投票

承诺被拒绝后可以“处理”。也就是说,在提供catch处理程序之前,可以调用promise的拒绝回调。这种行为对我来说有点麻烦,因为人们可以写...

var promise = new Promise(function(resolve) {
kjjdjf(); // this function does not exist });

......在这种情况下,承诺被默默拒绝。如果忘记添加一个catch处理程序,代码将继续静默运行而不会出现错误。这可能导致挥之不去且难以发现的错误。

在Node.js的情况下,有人谈到处理这些未处理的Promise拒绝并报告问题。这让我想到ES7 async / await。考虑这个例子:

async function getReadyForBed() {
  let teethPromise = brushTeeth();
  let tempPromise = getRoomTemperature();

  // Change clothes based on room temperature
  let temp = await tempPromise;
  // Assume `changeClothes` also returns a Promise
  if(temp > 20) {
    await changeClothes("warm");
  } else {
    await changeClothes("cold");
  }

  await teethPromise;
}

在上面的例子中,假设在满足getRoomTemperature之前,teethPromise被拒绝(错误:没有牙膏!)。在这种情况下,在等待teethPromise之前,将会有未处理的Promise拒绝。

我的观点是......如果我们认为未处理的Promise拒绝是一个问题,稍后由等待处理的Promise可能会无意中被报告为错误。然后,如果我们认为未处理的Promise拒绝不成问题,可能不会报告合法的错误。

对此的想法?

这与Node.js项目中的讨论有关:

Default Unhandled Rejection Detection Behavior

如果你这样编写代码:

function getReadyForBed() {
  let teethPromise = brushTeeth();
  let tempPromise = getRoomTemperature();

  // Change clothes based on room temperature
  return Promise.resolve(tempPromise)
    .then(temp => {
      // Assume `changeClothes` also returns a Promise
      if (temp > 20) {
        return Promise.resolve(changeClothes("warm"));
      } else {
        return Promise.resolve(changeClothes("cold"));
      }
    })
    .then(teethPromise)
    .then(Promise.resolve()); // since the async function returns nothing, ensure it's a resolved promise for `undefined`, unless it's previously rejected
}

当调用getReadyForBed时,它将同步创建最终(未返回)的promise - 它将具有与任何其他promise相同的“未处理拒绝”错误(当然,可能不是什么,取决于引擎)。 (我发现你的函数没有返回任何东西很奇怪,这意味着你的异步函数产生了未定义的承诺。

如果我现在做一个没有捕获的Promise,稍后再添加一个,大多数“未处理的拒绝错误”实现实际上会在我稍后处理它时收回警告。换句话说,async / await不会以任何我能看到的方式改变“未处理的拒绝”讨论。

要避免这个陷阱,请以这种方式编写代码:

async function getReadyForBed() {
  let teethPromise = brushTeeth();
  let tempPromise = getRoomTemperature();

  // Change clothes based on room temperature
  var clothesPromise = tempPromise.then(function(temp) {
    // Assume `changeClothes` also returns a Promise
    if(temp > 20) {
      return changeClothes("warm");
    } else {
      return changeClothes("cold");
    }
  });
  /* Note that clothesPromise resolves to the result of `changeClothes`
     due to Promise "chaining" magic. */

  // Combine promises and await them both
  await Promise.all(teethPromise, clothesPromise);
}

请注意,这应该可以防止任何未处理的承诺拒绝。


9
投票

“弃用警告:未处理的承诺拒绝被弃用”

TLDR:承诺有resolvereject,做一个reject没有捕获来处理它已被弃用,所以你必须至少有一个catch在顶层。


0
投票

当我实例化一个promise时,我将生成一个异步函数。如果函数运行良好,那么我调用RESOLVE然后流程继续在RESOLVE处理程序中,然后在THEN中。如果函数失败,则通过调用REJECT终止函数,然后流程在CATCH中继续。

在NodeJs中不推荐使用拒绝处理程序。您的错误只是一个警告,我在node.js github中读取它。我找到了这个。

DEP0018:未处理的承诺拒绝

类型:运行时

未处理的承诺拒绝已被弃用。将来,未处理的承诺拒绝将使用非零退出代码终止Node.js进程。

© www.soinside.com 2019 - 2024. All rights reserved.