获得第一个实现的承诺
Get first fulfilled promise
如果我有两个 promise A 和 B,只有一个会成功,我怎么才能得到哪个 fulfill 成功呢?我正在寻找类似于 Promise.race
的东西,但 return 只有第一个实现的承诺。我正在使用 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()
来完成此操作,因为它只是报告要完成的第一个承诺,如果第一个承诺被拒绝,它将报告拒绝。因此,它并没有按照您在问题中提出的要求报告第一个解决的承诺(即使在它之前完成了一些拒绝)。
仅供参考,the Bluebird promise library 有 Promise.some()
和 Promise.any()
可以为您处理这种情况。
反转promise的极性,然后你可以使用Promise.all
,因为它拒绝了第一个被拒绝的promise,反转后对应于第一个实现的promise:
const invert = p => new Promise((res, rej) => p.then(rej, res));
const firstOf = ps => invert(Promise.all(ps.map(invert)));
// Utility routines used only in testing.
const wait = ms => new Promise(res => setTimeout(() => res(ms), ms));
const fail = f => Promise.reject(f);
const log = p => p.then(v => console.log("pass", v), v => console.log("fail", v));
// Test.
log(firstOf([wait(1000), wait(500) ]));
log(firstOf([wait(1000), fail("f1")]));
log(firstOf([fail("f1"), fail("f2")]));
这将 return 第一个履行的承诺的价值,或者如果全部拒绝,则拒绝原因的数组。
//example 1
var promise_A = new Promise(function(resolve, reject) {
// выполнить что-то, возможно, асинхронно…
setTimeout(function(){
return resolve(10);
//return reject(new Error('ошибка'))
},10000)
});
var promise_B = new Promise(function(resolve, reject) {
// выполнить что-то, возможно, асинхронно…
setTimeout(function(){
return resolve(100);
},2000)
});
/*
//[100,10]
Promise.all([
promise_A,promise_B
]).then(function(results){
console.log(results)
});
*/
//100
Promise.race([
promise_A,promise_B
]).then(function(results){
console.log(results)
});
我也有同样的问题,试了一下。通过自己尝试这些问题,您会学到很多东西!
- 接受的答案非常优雅,但使用了
Promise.all
,这对学习 Promises 的人来说很有趣;在我看来也有点难以理解。
jfriend00
的回答与我的相似,但其逻辑超出了这里最重要的 Promises 基础知识。
我已经使用了已接受答案中的那些不错的辅助函数:
function firstPromise(promiseL, promiseR) {
return new Promise((resolve, reject) => {
promiseL.then(l => {
resolve(l);
}).catch(error => null);
promiseR.then(r => {
resolve(r);
}).catch(error => null);
promiseL.catch(errorL => {
promiseR.catch(errorR => {
reject(errorL + errorR);
})
})
})
}
const wait = ms => new Promise(res => setTimeout(() => res(ms), ms));
const log = p => p.then(v => console.log("pass", v), v => console.log("fail", v));
log(firstPromise(wait(1000), wait(500)));
log(firstPromise(wait(1000), Promise.reject("Bar")));
log(firstPromise( Promise.reject("Foo"), wait(500)));
log(firstPromise( Promise.reject("Foo"), Promise.reject("Bar")));
ES2021 / ES12 - Promise.any
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
正在解决
如果所有给定的承诺都被拒绝,则返回的承诺将被拒绝。
这是finished proposal,预定ES2021(预计2021年6月发布)
如果我有两个 promise A 和 B,只有一个会成功,我怎么才能得到哪个 fulfill 成功呢?我正在寻找类似于 Promise.race
的东西,但 return 只有第一个实现的承诺。我正在使用 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()
来完成此操作,因为它只是报告要完成的第一个承诺,如果第一个承诺被拒绝,它将报告拒绝。因此,它并没有按照您在问题中提出的要求报告第一个解决的承诺(即使在它之前完成了一些拒绝)。
仅供参考,the Bluebird promise library 有 Promise.some()
和 Promise.any()
可以为您处理这种情况。
反转promise的极性,然后你可以使用Promise.all
,因为它拒绝了第一个被拒绝的promise,反转后对应于第一个实现的promise:
const invert = p => new Promise((res, rej) => p.then(rej, res));
const firstOf = ps => invert(Promise.all(ps.map(invert)));
// Utility routines used only in testing.
const wait = ms => new Promise(res => setTimeout(() => res(ms), ms));
const fail = f => Promise.reject(f);
const log = p => p.then(v => console.log("pass", v), v => console.log("fail", v));
// Test.
log(firstOf([wait(1000), wait(500) ]));
log(firstOf([wait(1000), fail("f1")]));
log(firstOf([fail("f1"), fail("f2")]));
这将 return 第一个履行的承诺的价值,或者如果全部拒绝,则拒绝原因的数组。
//example 1
var promise_A = new Promise(function(resolve, reject) {
// выполнить что-то, возможно, асинхронно…
setTimeout(function(){
return resolve(10);
//return reject(new Error('ошибка'))
},10000)
});
var promise_B = new Promise(function(resolve, reject) {
// выполнить что-то, возможно, асинхронно…
setTimeout(function(){
return resolve(100);
},2000)
});
/*
//[100,10]
Promise.all([
promise_A,promise_B
]).then(function(results){
console.log(results)
});
*/
//100
Promise.race([
promise_A,promise_B
]).then(function(results){
console.log(results)
});
我也有同样的问题,试了一下。通过自己尝试这些问题,您会学到很多东西!
- 接受的答案非常优雅,但使用了
Promise.all
,这对学习 Promises 的人来说很有趣;在我看来也有点难以理解。 jfriend00
的回答与我的相似,但其逻辑超出了这里最重要的 Promises 基础知识。
我已经使用了已接受答案中的那些不错的辅助函数:
function firstPromise(promiseL, promiseR) {
return new Promise((resolve, reject) => {
promiseL.then(l => {
resolve(l);
}).catch(error => null);
promiseR.then(r => {
resolve(r);
}).catch(error => null);
promiseL.catch(errorL => {
promiseR.catch(errorR => {
reject(errorL + errorR);
})
})
})
}
const wait = ms => new Promise(res => setTimeout(() => res(ms), ms));
const log = p => p.then(v => console.log("pass", v), v => console.log("fail", v));
log(firstPromise(wait(1000), wait(500)));
log(firstPromise(wait(1000), Promise.reject("Bar")));
log(firstPromise( Promise.reject("Foo"), wait(500)));
log(firstPromise( Promise.reject("Foo"), Promise.reject("Bar")));
ES2021 / ES12 - Promise.any
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
正在解决
如果所有给定的承诺都被拒绝,则返回的承诺将被拒绝。
这是finished proposal,预定ES2021(预计2021年6月发布)