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]))
Run Code Online (Sandbox Code Playgroud)
现在,如果我执行上面的语句,它将按顺序运行.在我的实际用例中,数组是动态填充的,我需要myPromise()为每个成员执行该函数myArray.
我如何创建一个"可暂停的循环",它将为数组中的每个项循环,执行myPromise并等待承诺得到解决,然后再继续下一次迭代?
Ry-*_*Ry- 42
.then如果您可以像创建问题中的情况那样创建与数组元素一样多的promise,那么您可以将重复应用程序整齐地复制到折叠中:
myArray.reduce(
(p, x) =>
p.then(_ => myPromise(x)),
Promise.resolve()
)
Run Code Online (Sandbox Code Playgroud)
但是,例如,异步函数不需要:
const mapSeries = async (iterable, action) => {
for (const x of iterable) {
await action(x)
}
}
mapSeries(myArray, myPromise)
Run Code Online (Sandbox Code Playgroud)
这是优秀的诺言图书馆Bluebird内置的mapSeries:
Promise.mapSeries(myArray, myPromise)
Run Code Online (Sandbox Code Playgroud)
Runnable片段:
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)
})
myArray.reduce(
(p, x) =>
p.then(_ => myPromise(x)),
Promise.resolve()
)Run Code Online (Sandbox Code Playgroud)
Mas*_*ief 12
我知道我已经很晚了,我的回答与其他人发布的类似。但我想我可以发布一个更清晰的答案,这可能会对任何初学者有所帮助。
我们可以使用 Promise 工厂,而不是直接使用 Promise。由于 Promise 在使用 Promise 工厂创建后立即开始执行,因此我们延迟了 Promise 的创建。
在此示例中,我创建了 5 个,它们会在一秒钟后解析。我使用 PromiseCreator 来创建 Promise。现在该数组promises用于promiseCreator创建 5 个 Promise 实例。但数组promiseFactories包装promiseCreator在一个函数中,因此不会立即调用 Promise。使用时会被调用。
函数按顺序executeSequentially执行所有操作promiseLike。
promise传递数组时,结果是promise数组本身并行执行(实际上它们在创建后立即执行,而不是在调用此行时执行)。promiseFactory数组传递时,结果是新的 Promise,当先前的 Promise 完成执行时,就会创建 Promise。const promiseCreator = (i, time, text) => {
return new Promise(resolve => setTimeout(
() => resolve(console.log(`${i} ${text}`)),
time)
);
}
const promises = [
promiseCreator(1, 1000, "parallel"),
promiseCreator(2, 1000, "parallel"),
promiseCreator(3, 1000, "parallel"),
promiseCreator(4, 1000, "parallel"),
promiseCreator(5, 1000, "parallel"),
]
const promiseFactories = [
() => promiseCreator(1, 1000, "sequential"),
() => promiseCreator(2, 1000, "sequential"),
() => promiseCreator(3, 1000, "sequential"),
() => promiseCreator(4, 1000, "sequential"),
() => promiseCreator(5, 1000, "sequential"),
]
function executeSequentially(promiseLikeArray) {
var result = Promise.resolve();
promiseLikeArray.forEach(function (promiseLike) {
result = result.then(promiseLike);
});
return result;
}
executeSequentially(promises)
executeSequentially(promiseFactories)Run Code Online (Sandbox Code Playgroud)
不要创建一个承诺数组.创建一个返回promise的函数数组.
const f = x => new Promise(resolve => setTimeout(() => resolve(console.log(x)), 2000))
(async () => {
for (let job of [1, 2, 3, 4, 5, 6].map(x => () => f(x)))
await job()
})()
Run Code Online (Sandbox Code Playgroud)
Promise在创建后立即开始运行.因此,通过仅在完成当前承诺之后构造下一个承诺来确保顺序执行.
您可以使用async await功能来顺序运行承诺。这是一个片段
async function chainPromiseCalls(asyncFunctions=[],respectiveParams=[]){
for(let i=0;i<asyncFunctions.length;i++){
const eachResult = await asyncFunctions[i](...respectiveParams[i]);
// do what you want to do with each result
}
return ;
}
Run Code Online (Sandbox Code Playgroud)
对于并行,您可以在循环中调用每个异步函数一次,但如果您确实想获得它们的组合结果,您可以使用Promise.all
function parallelPromiseCalls(asyncFunctions=[],respectiveParams=[]){
return Promise.all(asyncFunctions.map((func,index)=>func(...respectiveParams[index])))
.then(resultsList=>{
resultsList.forEach((result,index)=>{
// do what you want to do with each result in the list
})
return ;
})
}
Run Code Online (Sandbox Code Playgroud)
注意:我将各个参数视为列表的列表,因为应该将多个参数传递给任何一个函数,否则,如果您必须仅向每个参数传递一个参数,那么您可以删除扩展运算符。
您也可以通过递归方法来实现 -executeSequentially调用自身:
function createPromise(x) {
return new Promise(res => {
setTimeout(() => {
console.log(x)
res(x);
}, x * 1000)
})
}
function executeSequentially(array) {
return createPromise(array.shift())
.then(x => array.length == 0 ? x : executeSequentially(array));
}
console.time('executeSequentially');
executeSequentially([1, 2, 3]).then(x => {
console.log('last value: ' + x);
console.timeEnd('executeSequentially');
});Run Code Online (Sandbox Code Playgroud)