解法1:for 循环 + await
简单的 for 循环是依次进行循环的,不像 Array.forEach,Array.map 方法是并发执行的,利用这一特点加 async / await 很容易写出下面这样的代码:
(async () => {
const sleep = (delay) => {
return new Promise((resolve, reject) => {
setTimeout((_) => resolve(), delay);
});
};
const task = (i) => {
return new Promise(async (resolve, reject) => {
await sleep(500);
console.log(`now is ${i}`);
++i;
resolve(i);
});
};
let param = 0;
for (let i = 0; i < 4; i++) {
param = await task(param);
}
})();
输出:
now is 0
now is 1
now is 2
now is 3
解法2:Array.prototype.reduce
关于 Array.prototype.reduce 方法相信大部分小伙伴初见时都是用来数组求和。
reduce有初始值
,积累值
,以及当前值
的概念。其中 积累值
可以看作是前一个值,通过返回积累值
又可以看作是 下一个值。使用reduce来解决问题的代码为:
const sleep = (delay) => {
return new Promise((resolve, reject) => {
setTimeout((_) => resolve(), delay);
});
};
const task = (i) => {
return new Promise(async (resolve, reject) => {
await sleep(500);
console.log(`now is ${i}`);
++i;
resolve(i);
});
};
[task, task, task, task].reduce(async (prev, task) => {
const res = await prev;
return task(res);
}, 0);
输出:
now is 0
now is 1
now is 2
now is 3
可以这样理解 prev
和 task
:
- prev:前一个 异步任务(promise)
- task:当前的异步任务
当前的异步任务需要上一个异步任务的结果作参数,故很显然要 await prev。