我目前正在做一些我要在数组中实现三个承诺的事情。目前看起来像这样
var a = await Promise.all([Promise1(), Promise2(), Promise3()]);
现在所有这些承诺都会返回true或false。但是目前我正在等待所有这些操作完成,只要其中一个返回true,我就可以继续。
我想到了实现此目标的方法,但似乎都有些丑陋。您将如何解决此任务?
答案 0 :(得分:12)
您可以创建一个new promise,一旦给定的诺言解析为print(df)
MultiIndex(levels=[['bar', 'baz', 'foo', 'qux'], ['one', 'two']],
labels=[[0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]],
names=['first', 'second'])
,它就会立即解决:
true
它的行为类似于Promise.race
,但仅在给定的一个promise解析为值function promiseRaceTrue(promises) {
return new Promise(function(resolve, reject) {
promises.forEach(promise =>
promise.then(val => val === true && resolve())
// TODO handle resolve with value of "false"?
// TODO handle rejection?
);
// TODO handle all resolved as "false"?
});
}
var a = await promiseRaceTrue([Promise1(), Promise2(), Promise3()]);
时才解析,而不是在任何给定的promise解析或拒绝时立即解决。
答案 1 :(得分:12)
您可以结合使用Promise.race
和Promise.all
:
function firstTrue(promises) {
const newPromises = promises.map(p => new Promise(
(resolve, reject) => p.then(v => v && resolve(true), reject)
));
newPromises.push(Promise.all(promises).then(() => false));
return Promise.race(newPromises);
}
测试以上代码:
function firstTrue(promises) {
const newPromises = promises.map(p => new Promise(
(resolve, reject) => p.then(v => v && resolve(true), reject)
));
newPromises.push(Promise.all(promises).then(() => false));
return Promise.race(newPromises);
}
var test = values => firstTrue(
values.map((v) => new Promise((resolve) => {
setTimeout(() => resolve(v), Math.round(Math.random() * 1000));
}))
).then((ret) => console.log(values, ret));
test([true, true, true]);
test([false, false, false]);
test([true, false, false]);
test([false, true, false]);
test([false, false, true]);
答案 2 :(得分:7)
可以使用Promise.race()并且仅在值为true时解析初始承诺
const doSomething = (bool, val)=>{
return new Promise((resolve, reject)=>{
if (bool){
resolve(val)
}
})
}
const promise1 = doSomething(false,'one')
const promise2 = doSomething(false,'two')
const promise3 = doSomething(true,'three')
const promise4 = doSomething(true,'four')
const promise5 = doSomething(true,'five')
Promise.race([promise1, promise2, promise3, promise4, promise5]).then(value => {
console.log('First true one to resolve is: ', value);
});
答案 3 :(得分:7)
您基本上想要some()
。
Promise.all()
无法正常工作,因为它将使您等待所有承诺完成。Promise.race()
单独行不通,因为它只返回1 Promise的分辨率。相反,我们需要接收一个Promises数组,并继续进行竞赛,直到其中一个返回true
为止,然后我们应该停止。如果它们都不是真的,我们仍然需要停下来,但是我们需要注意,它们都不是真的。
考虑以下示例与测试工具:
/**
* Promise aware setTimeout based on Angulars method
* @param {Number} delay How long to wait before resolving
* @returns {Promise} A resolved Promise to signal the timeout is complete
*/
function $timeout(delay) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), delay);
});
}
/**
* Return true (early) if any of the provided Promises are true
* @param {Function(arg: *): Boolean} predicate The test the resolved Promise value must pass to be considered true
* @param {Promise[]} arr The Promises to wait on
* @returns {Promise<Boolean>} Whether one of the the provided Promises passed the predicate
*/
async function some(predicate, arr) {
// Don't mutate arguemnts
const arrCopy = arr.slice(0);
// Wait until we run out of Promises
while(arrCopy.length){
// Give all our promises IDs so that we can remove them when they are done
const arrWithIDs = arrCopy.map((p, idx) => p.then(data => ({idx, data})));
// Wait for one of the Promises to resolve
const soon = await Promise.race(arrWithIDs);
// If it passes the test, we're done
if(predicate(soon.data))return true;
// Otherwise, remove that Promise and race again
arrCopy.splice(soon.idx, 1);
}
// No Promises passed the test
return false;
}
// Test harness
const tests = [
function allTrue(){
console.log(new Date());
return some((v)=>v, [
$timeout(1000).then(() => true),
$timeout(2000).then(() => true),
$timeout(3000).then(() => true)
]).then(d => {
console.log(d);
console.log(new Date());
});
},
function twoSecondsTrue(){
console.log(new Date());
return some((v)=>v, [
$timeout(1000).then(() => false),
$timeout(2000).then(() => true),
$timeout(3000).then(() => true)
]).then(d => {
console.log(d);
console.log(new Date());
});
},
function threeSecondsTrue(){
console.log(new Date());
return some((v)=>v, [
$timeout(1000).then(() => false),
$timeout(2000).then(() => false),
$timeout(3000).then(() => true)
]).then(d => {
console.log(d);
console.log(new Date());
});
},
function allFalse(){
console.log(new Date());
return some((v)=>v, [
$timeout(1000).then(() => false),
$timeout(2000).then(() => false),
$timeout(3000).then(() => false)
]).then(d => {
console.log(d);
console.log(new Date());
});
}
]
tests.reduce((acc, curr) => acc.then(()=>curr()), Promise.resolve());
// 1 Second true
2018-07-03T18:41:33.264Z
true
2018-07-03T18:41:34.272Z
// 2 Seconds true
2018-07-03T18:41:34.273Z
true
2018-07-03T18:41:36.274Z
// 3 Seconds true
2018-07-03T18:41:36.274Z
true
2018-07-03T18:41:39.277Z
// 3 Seconds false
2018-07-03T18:41:39.277Z
false
2018-07-03T18:41:42.282Z
答案 4 :(得分:5)
超越str的答案,我想添加提供回调的功能,这样它就可以在超过true/false
个承诺中使用。
添加回调将允许测试任何Promise的结果,并返回成功匹配回调过滤器的诺言(应返回true/false
值)。
Promise.until = function(callback, ...promises) {
return new Promise(function(resolve, reject) {
promises.forEach(promise =>
promise.then(val => callback(val) === true && resolve(val))
)
})
}
// Create some functions that resolve true/false
function Promise1() {return new Promise(resolve => setTimeout(()=> resolve(false), 1000))}
function Promise2() {return new Promise(resolve => setTimeout(()=> resolve(true), 3000))}
function Promise3() {return new Promise(resolve => setTimeout(()=> resolve(false), 1000))}
// Create som functions that resolve objects
function Promise4() {return new Promise(resolve => setTimeout(()=> resolve({a:1}), 1000))}
function Promise5() {return new Promise(resolve => setTimeout(()=> resolve({a:2}), 3000))}
function Promise6() {return new Promise(resolve => setTimeout(()=> resolve({a:123}), 1000))}
// Create some functions that resolve strings
function Promise7() {return new Promise(resolve => setTimeout(()=> resolve('Brass'), 1000))}
function Promise8() {return new Promise(resolve => setTimeout(()=> resolve('Monkey'), 500))}
function Promise9() {return new Promise(resolve => setTimeout(()=> resolve(['Brass', 'Monkey']), 100))}
// Once one resolves `true` we will catch it
Promise.until(result => result === true, Promise1(), Promise2(), Promise3())
.then(result => console.log(result));
// Once one resolves where `a` equals 123, we will catch it
Promise.until(result => result.a === 123, Promise4(), Promise5(), Promise6())
.then(result => console.log(result));
// Once one resolves where `a` equals 123, we will catch it
Promise.until(result => result === 'Monkey', Promise7(), Promise8(), Promise9())
.then(result => console.log(result));
答案 5 :(得分:0)
好的,我将保留接受的答案。但是我根据自己的需要对它做了一些修改,因为我认为此书更易于阅读和理解
const firstTrue = Promises => {
return new Promise((resolve, reject) => {
// map each promise. if one resolves to true resolve the returned promise immidately with true
Promises.map(p => {
p.then(result => {
if(result === true){
resolve(true);
return;
}
});
});
// If all promises are resolved and none of it resolved as true, resolve the returned promise with false
Promise.all(Promises).then(() => {
resolve(Promises.indexOf(true) !== -1);
});
});
}