var myArray = [1, 2, 3, 4, 5, 6]
function myPromise(num){
return new Promise(res => {
window.setTimeout(()=>{
res( console.log("done: " + num) )
},2000)
})
}
myPromise(myArray[0])
.then(x => myPromise(myArray[1]))
.then(x => myPromise(myArray[2]))
.then(x => myPromise(myArray[3]))
.then(x => myPromise(myArray[4]))
.then(x => myPromise(myArray[5]))
现在,如果我执行上面的语句,它将按顺序运行。在我的实际用例中,数组是动态填充的,我需要为 myArray
中的每个成员执行 myPromise()
函数。
如何制作一个“可暂停循环”,该循环将为数组中的每个项目循环,执行 myPromise
并等待 promise 得到解决,然后再继续下一次迭代?
请您参考如下方法:
如果您可以像问题中的情况那样创建与数组元素一样多的 Promise,则可以非常整齐地重复应用 .then
:
myArray.reduce(
(p, x) =>
p.then(() => myPromise(x)),
Promise.resolve()
)
但考虑到支持,异步函数是更好的选择。它具有良好的可读性,并且具有 O(1) 而不是 O(n) 的内存开销。
const forEachSeries = async (iterable, action) => {
for (const x of iterable) {
await action(x)
}
}
forEachSeries(myArray, myPromise)
如果你想将返回值收集为数组,那就是:
const mapSeries = async (iterable, fn) => {
const results = []
for (const x of iterable) {
results.push(await fn(x))
}
return results
}
或者,没有异步函数支持,
const mapSeries = (iterable, fn) => {
const iterator = iterable[Symbol.iterator]()
const results = []
const go = () => {
const {value, done} = iterator.next()
if (done) {
return results
}
return fn(value).then(mapped => {
results.push(mapped)
return go()
})
}
return Promise.resolve().then(go)
}
可运行片段:
const myArray = [1, 2, 3, 4, 5, 6]
const sleep = ms =>
new Promise(res => {
setTimeout(res, ms)
})
const myPromise = num =>
sleep(500).then(() => {
console.log('done: ' + num)
})
const forEachSeries = async (iterable, action) => {
for (const x of iterable) {
await action(x)
}
}
forEachSeries(myArray, myPromise)
.then(() => {
console.log('all done!')
})