承诺,和解与诺言兑现与拒绝 [英] Promise.settle and promise fulfillment vs rejection

查看:76
本文介绍了承诺,和解与诺言兑现与拒绝的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码,其中包含Bluebird的Promise.settle的简化实现:

Consider the following code that contains a simplified implementation of Bluebird's Promise.settle:

var a = Promise.reject('a');
var b = Promise.resolve('b');
var c = Promise.resolve('c');

var promises = [a,b,c];

function settled(promises) {
  var alwaysFulfilled = promises.map(function (p) {
    return p.then(
      function onFulfilled(value) {
        return { state: 'fulfilled', value: value };
      },
      function onRejected(reason) {
        return { state: 'rejected', reason: reason };
      }
    );
  });
  return Promise.all(alwaysFulfilled);
}

//Update status message once all requests finish
settled(promises).then(function (outcomes) {
  var count = 0;
  outcomes.forEach(function (outcome) {
    if (outcome.state == 'fulfilled') count++;
  });

  console.log(count + ' out of ' + outcomes.length + ' balances were updated');
});

这将记录已更新3个余额中的2个".为什么这与普通的Promise.all不同?

This will log "2 out of 3 balances were updated". Why does this work differently than a plain Promise.all? Shouldn't alwaysFulfilled still contain a rejected promise as its first element?

答案似乎在于我对诺言如何运作的困惑.如果我在控制台中创建了一个被拒绝的承诺,然后按如下所示进行操作:

The answer seems to lie in my confusion over how promises work. If I create a rejected promise in the console and .then it like so:

var a = Promise.reject('a');
var b = a.then(function() {}, undefined);
var c = a.then(undefined, function() {});

a
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: "a"}
b
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: "a"}
c
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: undefined}

为什么c被解析"?

推荐答案

理解问题的关键是,当您在.then().catch()中提供拒绝处理程序时,您便在告诉promise系统您正在处理"拒绝.因此,除非您的拒绝处理程序本身抛出或返回被拒绝的承诺,否则该拒绝处理程序的返回值将变为已实现的承诺,而不是被拒绝的承诺.对此的更多解释如下...

The key to understanding your question is that when you supply a reject handler in a .then() or with a .catch(), then you are telling the promise system that you're "handling" the rejection. So, unless your reject handler itself throws or returns a rejected promise itself, then the return value of that reject handler goes into a fulfilled promise, not a rejected promise. Much more on this explained below...

事实上,反之亦然.如果您有拒绝处理程序,并且根据拒绝的类型,希望拒绝继续传播回拒绝的承诺,则必须抛出拒绝处理程序中的错误或返回拒绝的承诺.

In fact, the inverse is true also. If you have a reject handler and based on the type of rejection, you want the rejection to continue to propagate back into a rejected promise, you have to either throw the error from the reject handler or return a rejected promise.

这将记录已更新3个余额中的2个".为什么这项工作 与普通的Promise.all不同吗?

This will log "2 out of 3 balances were updated". Why does this work differently than a plain Promise.all?

Promise.all()在获得给它的承诺列表中的第一个拒绝后立即返回一个被拒绝的承诺.它不一定返回所有结果,并且如果您通过的任何诺言被拒绝,它也将返回被拒绝.一旦兑现了一项承诺,它实际上就放弃了.这就是Promise.settle()的意义.即使某些结果被拒绝,它也将为您提供所有结果,然后您便可以仔细查看所有结果.

Promise.all() returns a rejected promise as soon as it gets the first rejection in the list of promises given to it. It does not necessarily return all results and it returns rejected if any promise you passed it is rejected. It essentially gives up as soon as one promise is rejected. That's the point of Promise.settle(). It will gives you all the results, even if some are rejected and you can then cull through all the results.

不一定总是履行仍包含被拒绝的承诺,因为其 第一个元素?

Shouldn't alwaysFulfilled still contain a rejected promise as its first element?

如下所述,当您在.then()中有拒绝处理程序,并且该拒绝处理程序没有throw或返回被拒绝的承诺(例如,像您所做的那样返回正常值)时,则该承诺被拒绝为被视为已处理,并且来自.then()处理程序的结果承诺得以实现,而不是被拒绝.下面的步骤中有更多说明...

As explained below, when you have a reject handler in a .then() and that reject handler does not throw or return a rejected promise (e.g. it returns a normal value like you are doing), then that promise rejection is considered handled and the resulting promise from the .then() handler is fulfilled, not rejected. More explanation in steps below...

答案似乎在于我对诺言如何运作的困惑.如果我 在控制台中创建一个被拒绝的诺言,然后像这样... 为什么c被解析"?

The answer seems to lie in my confusion over how promises work. If I create a rejected promise in the console and .then it like so... Why is c "resolved"?

首先,.then()返回一个新的承诺.因此a.then()不返回a.它正在返回一个新的承诺,它是.then()处理程序中发生的事情的结果.

First off, .then() returns a new promise. So a.then() is not returning a. It's returning a new promise that is the product of what happens in the .then() handler.

执行此操作时:

var c = Promise.reject('a').then(undefined, function() {});

这是正在发生的事情:

  1. 您以原因'a'创建被拒绝的承诺.
  2. 您将.then()链接到它,这会创建一个新的Promise,并将其返回到变量c.
  3. 然后,因为原始的承诺被拒绝,所以调用了.then()的第二个处理程序.在调试或设计代码时,请记住,它始终是异步调用的(有时会使调试器中的人员感到困惑).
  4. 您从该拒绝处理程序返回undefined.此时,Promise系统将拒绝视为已处理",并且.then()的结果是带有undefined值(这是您的处理程序返回的值)的已兑现承诺.
  1. You create a rejected promise with reason 'a'.
  2. You chain .then() to it which creates a new promise and returns that into your variable c.
  3. Then, because the original promise was rejected, the second handler to .then() is called. When debugging or designing your code, remember this is always called asynchronously (this can confuse people in the debugger sometimes).
  4. You return undefined from that reject handler. At this point, the Promise system considers the rejection "handled" and the result of .then() is a fulfilled promise with an undefined value (that's what your handler returned).

如果您希望结果仍然被拒绝,则可以按throw键,也可以从拒绝处理程序返回被拒绝的诺言.这样,您就可以处理"拒绝并保持承诺链成功进行.另外,未处理的拒绝将导致被拒绝的承诺,但是拥有拒绝处理程序将告诉promise系统您的代码正在处理拒绝,并且所产生的承诺将根据拒绝处理程序的返回结果形成.

If you want the result to still be rejected, then you can either throw or you can return a rejected promise from your reject handler. It is done this way so you can "handle" a rejection and keep the promise chain going successfully. Also, an unhandled rejection will result in a rejected promise, but having a reject handler tells the promise system that your code is taking care of the rejection and the resulting promise will be formed based on the return result from the reject handler.

因此,所有这些都会导致c被拒绝:

So, all these would result in c being rejected:

// no reject handler
var c = a.then(function() {});

// throw from reject handler 
var c = a.then(undefined, function() { throw new Error("whatever")});    

// return rejected promise from reject handler
var c = a.then(undefined, function() { return Promise.reject("whatever")});   

但是,如果您有拒绝处理程序,但它既没有throw也不返回拒绝的诺言,则将拒绝视为已处理",并使用您的处理程序返回的任何值来解决所产生的诺言.

But, if you have a reject handler and it doesn't either throw or return a rejected promise, then the rejection is considered "handled" and the resulting promise is resolved with whatever value your handler returns.

这篇关于承诺,和解与诺言兑现与拒绝的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆