Javascript 先兑现诺言
如果我有两个承诺A和B,其中只有一个会成功,我怎么能得到其中一个成功实现?我正在寻找类似于Javascript 先兑现诺言,javascript,node.js,promise,es6-promise,Javascript,Node.js,Promise,Es6 Promise,如果我有两个承诺A和B,其中只有一个会成功,我怎么能得到其中一个成功实现?我正在寻找类似于Promise.race的东西,但它只会返回第一个实现的承诺。我使用的是ES6中的承诺。如果您希望第一个承诺能够成功解决,并且希望忽略在此之前出现的任何拒绝,那么您可以使用类似以下内容: // returns the result from the first promise that resolves // or rejects if all the promises reject - then retu
Promise.race
的东西,但它只会返回第一个实现的承诺。我使用的是ES6中的承诺。如果您希望第一个承诺能够成功解决,并且希望忽略在此之前出现的任何拒绝,那么您可以使用类似以下内容:
// returns the result from the first promise that resolves
// or rejects if all the promises reject - then return array of rejected errors
function firstPromiseResolve(array) {
return new Promise(function(resolve, reject) {
if (!array || !array.length) {
return reject(new Error("array passed to firstPromiseResolve() cannot be empty"));
}
var errors = new Array(array.length);
var errorCntr = 0;
array.forEach(function (p, index) {
// when a promise resolves
Promise.resolve(p).then(function(val) {
// only first one to call resolve will actually do anything
resolve(val);
}, function(err) {
errors[index] = err;
++errorCntr;
// if all promises have rejected, then reject
if (errorCntr === array.length) {
reject(errors);
}
});
});
});
}
我不知道如何使用Promise.race()
,因为它只报告要完成的第一个承诺,如果第一个承诺被拒绝,它将报告拒绝。所以,它并不是按照你在问题中提出的要求去做,即报告解决的第一个承诺(即使一些拒绝在它之前完成)
仅供参考,它既有
Promise.some()
又有Promise.any()
,可以为您处理这种情况。反转承诺的极性,然后您可以使用Promise.all
,因为它拒绝了第一个被拒绝的承诺,在反转后对应于第一个履行的承诺:
const invert=p=>newpromise((res,rej)=>p.then(rej,res));
const firstOf=ps=>invert(Promise.all(ps.map(invert));
//仅在测试中使用的实用程序例程。
const wait=ms=>newpromise(res=>setTimeout(()=>res(ms),ms));
const fail=f=>Promise.reject(f);
const log=p=>p.then(v=>console.log(“通过”,v),v=>console.log(“失败”,v));
//测试。
日志(第一个([等待(1000),等待(500)]);
日志(第一个([等待(1000),失败(“f1”)));
日志(第一个([失败(“f1”)、失败(“f2”))代码>我问了同样的问题,试了一下。通过自己尝试这些问题,你学到了很多
公认的答案非常优雅,但使用了承诺。所有的都为学习承诺的人带来了乐趣;也有点难以理解
jfriend00
的答案与我的答案相似,但其逻辑超出了承诺的基本原则,而这在这里是最重要的李>
我已经使用了公认答案中的这些很好的帮助函数:
功能第一承诺(承诺人、承诺人){
返回新承诺((解决、拒绝)=>{
然后(l=>{
决议(l);
}).catch(错误=>null);
promiseR.then(r=>{
决议(r);
}).catch(错误=>null);
承诺捕获(错误=>{
promiseR.catch(error=>{
拒绝(errorL+ERROR);
})
})
})
}
const wait=ms=>newpromise(res=>setTimeout(()=>res(ms),ms));
const log=p=>p.then(v=>console.log(“通过”,v),v=>console.log(“失败”,v));
日志(firstPromise(等待(1000),等待(500));
日志(firstPromise(等待(1000),Promise.reject(“Bar”));
日志(firstPromise(Promise.reject(“Foo”),wait(500));
日志(第一承诺(承诺。拒绝(“Foo”)、承诺。拒绝(“Bar”))代码>ES2021/ES12-Promise.any
承诺。任何
-首先履行的承诺获胜
const promiseA = Promise.reject();
const promiseB = new Promise((resolve) => setTimeout(resolve, 100, 'succeed'));
const promises = [promiseA, promiseB];
Promise.race(promises).then((value) => console.log(value)); // rejected promise
Promise.any(promises).then((value) => console.log(value)); // "succeed"
请注意,any
忽略了第一个被拒绝的承诺-promiseA
,因为promiseB
正在被解析
如果所有给定的承诺都被拒绝,那么返回的承诺将被拒绝
这是并且计划在ES2021(预计于2021年6月发布)您应该使用p.then(…,…)
而不是p.then(…);p、 捕获(…)
以避免未处理rejections@Bergi-哪里有未经处理的拒绝?如果p
拒绝,则p的结果。然后(…)
是一个被拒绝且从未处理过的承诺。我说的是结果。在q=p.then(…);p、 catch(…)
对p
的拒绝被处理(两次),是的,但对q
的拒绝从未被处理,因此被全局报告,这是错误的。ES7指定了未经处理的拒绝如何工作,并且它们确实错误地使用了您的原始代码。你的书关于。然后(…)。catch(…)
是正确的,但它说的是一般性的,这是我们想要。然后(…,…)
(我们永远不希望fn1
和fn2
两者都被称为)的一种特殊情况,这并不是完全错误的,因为你的fn1
从不抛出,但它更干净,效率更高,如果您在fn1
中犯了错误(如打字错误),将正确报告。您正在寻找承诺。任何(,…)聪明。这不是第一次在promise land中使用倒置的概念。@jfriend00对,这种技术至少在另一个答案中显示出来了,所以我无法找到,不是原创的。这是一个聪明的破解方法。@torazaburo,你可能看到过,它也可以写成promise.prototype.invert()
和promise.any()
-这将返回解决或拒绝的承诺,而不是第一个实现的承诺。西里尔文的注释是怎么回事?
const promiseA = Promise.reject();
const promiseB = new Promise((resolve) => setTimeout(resolve, 100, 'succeed'));
const promises = [promiseA, promiseB];
Promise.race(promises).then((value) => console.log(value)); // rejected promise
Promise.any(promises).then((value) => console.log(value)); // "succeed"