async/await 的優(yōu)勢在于處理 then 鏈
單一的 Promise 鏈并不能發(fā)現(xiàn) async/await 的優(yōu)勢仅炊,但是看铆,如果需要處理由多個(gè) Promise 組成的 then 鏈的時(shí)候查近,優(yōu)勢就能體現(xiàn)出來了(很有意思赫悄,Promise 通過 then 鏈來解決多層回調(diào)的問題寺酪,現(xiàn)在又用 async/await 來進(jìn)一步優(yōu)化它)裸准。
假設(shè)一個(gè)業(yè)務(wù),分多個(gè)步驟完成柜思,每個(gè)步驟都是異步的希太,而且依賴于上一個(gè)步驟的結(jié)果。我們?nèi)匀挥?setTimeout
來模擬異步操作:
/**
* 傳入?yún)?shù) n酝蜒,表示這個(gè)函數(shù)執(zhí)行的時(shí)間(毫秒)
* 執(zhí)行的結(jié)果是 n + 200誊辉,這個(gè)值將用于下一步驟
*/
function takeLongTime(n) {
return new Promise(resolve => {
setTimeout(() => resolve(n + 200), n);
});
}
function step1(n) {
console.log(`step1 with ${n}`);
return takeLongTime(n);
}
function step2(n) {
console.log(`step2 with ${n}`);
return takeLongTime(n);
}
function step3(n) {
console.log(`step3 with ${n}`);
return takeLongTime(n);
}
現(xiàn)在用 Promise 方式來實(shí)現(xiàn)這三個(gè)步驟的處理
function doIt() {
console.time("doIt");
const time1 = 300;
step1(time1)
.then(time2 => step2(time2))
.then(time3 => step3(time3))
.then(result => {
console.log(`result is ${result}`);
console.timeEnd("doIt");
});
}
doIt();
// c:\var\test>node --harmony_async_await .
// step1 with 300
// step2 with 500
// step3 with 700
// result is 900
// doIt: 1507.251ms
輸出結(jié)果 result
是 step3()
的參數(shù) 700 + 200
= 900
。doIt()
順序執(zhí)行了三個(gè)步驟亡脑,一共用了 300 + 500 + 700 = 1500
毫秒堕澄,和 console.time()/console.timeEnd()
計(jì)算的結(jié)果一致。
如果用 async/await 來實(shí)現(xiàn)呢霉咨,會(huì)是這樣
async function doIt() {
console.time("doIt");
const time1 = 300;
const time2 = await step1(time1);
const time3 = await step2(time2);
const result = await step3(time3);
console.log(`result is ${result}`);
console.timeEnd("doIt");
}
doIt();
結(jié)果和之前的 Promise 實(shí)現(xiàn)是一樣的蛙紫,但是這個(gè)代碼看起來是不是清晰得多,幾乎跟同步代碼一樣
還有更酷的
現(xiàn)在把業(yè)務(wù)要求改一下途戒,仍然是三個(gè)步驟坑傅,但每一個(gè)步驟都需要之前每個(gè)步驟的結(jié)果。
function step1(n) {
console.log(`step1 with ${n}`);
return takeLongTime(n);
}
function step2(m, n) {
console.log(`step2 with ${m} and ${n}`);
return takeLongTime(m + n);
}
function step3(k, m, n) {
console.log(`step3 with ${k}, ${m} and ${n}`);
return takeLongTime(k + m + n);
}
這回先用 async/await 來寫:
async function doIt() {
console.time("doIt");
const time1 = 300;
const time2 = await step1(time1);
const time3 = await step2(time1, time2);
const result = await step3(time1, time2, time3);
console.log(`result is ${result}`);
console.timeEnd("doIt");
}
doIt();
// c:\var\test>node --harmony_async_await .
// step1 with 300
// step2 with 800 = 300 + 500
// step3 with 1800 = 300 + 500 + 1000
// result is 2000
// doIt: 2907.387ms
除了覺得執(zhí)行時(shí)間變長了之外喷斋,似乎和之前的示例沒啥區(qū)別把涠尽!別急星爪,認(rèn)真想想如果把它寫成 Promise 方式實(shí)現(xiàn)會(huì)是什么樣子浆西?
function doIt() {
console.time("doIt");
const time1 = 300;
step1(time1)
.then(time2 => {
return step2(time1, time2)
.then(time3 => [time1, time2, time3]);
})
.then(times => {
const [time1, time2, time3] = times;
return step3(time1, time2, time3);
})
.then(result => {
console.log(`result is ${result}`);
console.timeEnd("doIt");
});
}
doIt();
有沒有感覺有點(diǎn)復(fù)雜的樣子?那一堆參數(shù)處理顽腾,就是 Promise 方案的死穴—— 參數(shù)傳遞太麻煩了近零,看著就暈!
洗洗睡吧
就目前來說抄肖,已經(jīng)理解 async/await 了吧久信?但其實(shí)還有一些事情沒提及——Promise 有可能 reject 啊,怎么處理呢漓摩?如果需要并行處理3個(gè)步驟裙士,再等待所有結(jié)果,又該怎么處理呢幌甘?
阮一峰老師已經(jīng)說過了潮售,我就懶得說了。