1合是、JS依次執(zhí)行多項(xiàng)異步任務(wù)
- 有時候,我們希望批量執(zhí)行一組異步任務(wù)飒赃,但是不是并行利花,而是依次執(zhí)行,這組任務(wù)是動態(tài)的盒揉,在一個數(shù)組里晋被,當(dāng)然我們可以用 for 循環(huán)然后一個一個 await 執(zhí)行兑徘,但是還有另外一種方式:
async function taskReducer(promise, action){
let res = await promise;
return action(res);
}
function sleep(ms){
return new Promise(resolve => setTimeout(resolve, ms));
}
async function asyncTask(i){
await sleep(500);
console.log(`task ${i} done`);
return ++i;
}
[asyncTask, asyncTask, asyncTask].reduce(taskReducer, 0);
在上面的例子里刚盈,我們定義了一個 taskReducer:
async function taskReducer(promise, action){
let res = await promise;
return action(res);
}
這個 reducer 的兩個參數(shù)是 promise 和 action,promise 是代表當(dāng)前任務(wù)的 promise挂脑,而 action 是下一個要執(zhí)行的任務(wù)藕漱。我們可以 await 當(dāng)前 promise 執(zhí)行當(dāng)前任務(wù),然后將執(zhí)行結(jié)果傳給下一個 action 就可以了崭闲。
這樣我們可以調(diào)用:
[task1, task2, task3, ...].reduce(taskReducer, init);
不管這些任務(wù)是同步還是異步都可以被依次執(zhí)行肋联。需要注意的是,每一個任務(wù)的返回值將是下一個任務(wù)的輸入 promise 或者 value刁俭。
2橄仍、generator 與 async/await 一同使用
將上面的代碼進(jìn)一步擴(kuò)展,我們發(fā)現(xiàn),它可以支持 generator 與 async/await 一同使用:
async function reducer(promise, action){
let res = await promise;
return action(res);
}
function tick(i){
console.log(i);
return new Promise(resolve => setTimeout(()=>resolve(++i), 1000));
}
function continuous(...functors){
return async function(input){
return await functors.reduce(reducer, input)
}
}
function * timing(count = 5){
for(let i = 0; i < count; i++){
yield tick;
}
}
continuous(...timing(10))(0);
在上面的例子里侮繁,我們定義了一個計(jì)時 tick 函數(shù)虑粥,我們通過 timing 來連續(xù)調(diào)用它,而 timing 是一個 generator宪哩,計(jì)時器顯然是異步函數(shù)娩贷,然而我們可以:
continuous(...timing(10))(0);
而這里的 continuous 其實(shí)就是前面的 reduce 的封裝。