js有不少異步處理的解決方案,而async/await
就是其中的一種,最近有在學習和運用koa,在服務端中,不多用到promise,而是選擇了更加優雅的async/await
。固然,一種新方案的出現,咱們不光須要學會怎麼寫,也要學會他的原理。express
async/await
從字面意思上很好理解,async
是異步的意思,await
有等待的意思,而二者的用法上也是如此。async
用於申明一個function
是異步的,而await
用於等待一個異步方法執行完成。promise
async的語法很簡單,就是在函數開頭加一個關鍵字,示例以下:bash
async function f() {
return 1;
}
複製代碼
async關鍵字的意思很簡單,就是函數返回的是一個promise。koa
async function f() {
return 1;
}
f().then((res) => {
console.log(res)
}) // 1
複製代碼
async函數會返回一個promise對象,若是function中返回的是一個值,async直接會用Promise.resolve()
包裹一下返回。異步
關鍵詞await是等待的意思,那麼他在等什麼呢? 在MDN上寫的是:async
[return_value] = await expression;
複製代碼
等的是一個表達式,那麼表達式,能夠是一個常量,變量,promise,函數等。函數
function getSomething() {
return "something";
}
async function testAsync() {
return Promise.resolve("hello async");
}
async function test() {
const v1 = await getSomething();
const v2 = await testAsync();
console.log(v1, v2);
}
test(); // something hello async
複製代碼
await操做符等的是一個返回的結果,那麼若是是同步的狀況,那就直接返回了。學習
那若是是異步的狀況呢,異步的狀況下,await會阻塞整一個流程,直到結果返回以後,纔會繼續下面的代碼。ui
阻塞代碼是一個很可怕的事情,而async函數,會被包在一個promise中,異步去執行。因此await只能在async函數中使用,若是在正常程序中使用,會形成整個程序阻塞,得不償失。 spa
promise並非只有一種resolve,還有一種reject的狀況。而await只會等待一個結果,那麼發生錯誤了該怎麼處理呢?
async function myFunction() {
try {
await Promise.reject('1');
} catch (err) {
console.log(err);
}
}
myFunction(); // 1
複製代碼
async function myFunction() {
await Promise.reject('1').catch((err) => {
console.log(err);
});
}
myFunction(); // 1
複製代碼
promise最大的問題就是在於業務複雜以後,then內部的邏輯也變得複雜,或者循環的異步嵌套場景等,會寫出來不那麼優美。
我隨意列舉一個嵌套的例子,而後分別用async/await
和promise
,你就能感覺到二者之間的差距:
function takeLongTime(n) {
return new Promise(resolve => {
setTimeout(() => resolve(n), n);
});
}
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);
}
複製代碼
takeLongTime起到的做用就是延時以後給出延時的數據。
step1表明第一步延時了多久。
step2表明第一步和第二部總共延時了多久。
step3表明第一步、第二步和第三步一共延時了多久。
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();
複製代碼
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();
複製代碼
在這種複雜邏輯中,咱們就能發現async/await
確實比then鏈有優點。
async/await是一種異步的解決方案,而koa中支持這一特性,因此,在基於koa來寫服務端代碼的時候,這種語法糖不可避免,學習和運用它是咱們的必修課。