gpt4 book ai didi

javascript - Promise.settle 和 promise 履行与拒绝

转载 作者:行者123 更新时间:2023-11-29 18:04:51 25 4
gpt4 key购买 nike

考虑以下代码,其中包含 Bluebird 的 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 不同? alwaysFulfilled 不应该仍然包含一个被拒绝的 promise 作为它的第一个元素吗?

答案似乎在于我对 promises 的运作方式感到困惑。如果我在控制台中创建了一个被拒绝的 promise ,那么它就像这样:

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 ,否则该拒绝处理程序的返回值将进入一个已履行的 promise ,而不是一个被拒绝的 promise 。下面将对此进行更多解释......

其实反之亦然。如果您有拒绝处理程序并且基于拒绝的类型,您希望拒绝继续传播回被拒绝的 promise ,您必须从拒绝处理程序中抛出错误或返回被拒绝的 promise 。

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

Promise.all() 在收到给定的 promise 列表中的第一个拒绝后立即返回一个被拒绝的 promise 。它不一定返回所有结果,如果您通过的任何 promise 被拒绝,它会返回拒绝。一旦一个 promise 被拒绝,它基本上就放弃了。这就是 Promise.settle() 的意义所在。它会为您提供所有结果,即使有些结果被拒绝,您也可以筛选所有结果。

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

如下所述,当您在 .then() 中有一个拒绝处理程序并且该拒绝处理程序不会抛出或返回一个被拒绝的 promise (例如,它返回一个正常值,就像你正在做的那样),那么该 promise 拒绝被认为已处理,并且来自 .then() 处理程序的结果 promise 得到履行,而不是被拒绝。以下步骤中的更多解释...

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() 返回一个新的 promise 。所以 a.then() 没有返回 a。它返回一个新的 promise ,它是 .then() 处理程序中发生的事情的产物。

当你这样做时:

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

这是正在发生的事情:

  1. 您创建了一个拒绝的 promise ,原因是 'a'
  2. 您将 .then() 链接到它,这会创建一个新的 promise 并将其返回到您的变量 c 中。
  3. 然后,因为原始 promise 被拒绝,所以调用 .then() 的第二个处理程序。在调试或设计代码时,请记住这始终是异步调用的(这有时会使调试器中的人感到困惑)。
  4. 您从该拒绝处理程序返回 undefined。此时,Promise 系统认为拒绝“已处理”并且 .then() 的结果是具有 undefined 值的 fulfilled promise(这就是您的处理程序返回的内容) .

如果您希望结果仍然被拒绝,那么您可以throw 或者您可以从拒绝处理程序中返回一个被拒绝的 promise 。以这种方式完成,因此您可以“处理”拒绝并保持 promise 链成功运行。此外,未处理的拒绝将导致被拒绝的 promise ,但拥有拒绝处理程序会告诉 promise 系统您的代码正在处理拒绝,并且将根据拒绝处理程序的返回结果形成最终的 promise 。

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

// 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")});

但是,如果你有一个拒绝处理程序并且它既不抛出也不返回被拒绝的 promise ,那么拒绝被认为是“已处理”并且得到的 promise 将以你的处理程序的任何值解决返回。

关于javascript - Promise.settle 和 promise 履行与拒绝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32160055/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com