遇到個五連回調的代碼,真的是地獄級拷打,用async await
進行了一波改寫,頓時神清氣爽,總結一下。
顧名思義,async
是異步的簡寫,await
是 async await
的簡寫。所以async就是用於聲明一個function
是異步的,而await
就是用來等待這個異步方法執行完成的。另外,規定await
只能在async
中使用。
async作用及工作原理
先看下async
是怎麼處理返回值的
async function testAsync() {
return "hello world";
}
const result = testAsync();
console.log(result);// Promise {'hello world'}
可見,async
返回一個Promise
對象。如果在async
函數中直接return
一個值,那麼async
會把這個值通過Promise.resolve()
封裝成Promise
對象。Promise
的特點——無等待,所以在沒有使用await
的情況下,async
會立即執行,不會阻塞後面的代碼。
await在等誰呢?
原以爲,await
在等待async
的函數完成,等async
的訊息。看了文檔後,await
等待的其實是一個表達式,這個表達式的計算結果是Promise
對象或者其它值。
await
不僅僅用於等Promise
對象,它可以等任意表達式的結果,所以await
是可以接普通函數的。
function getValue() {
return 123;
}
async function testAsync() {
return Promise.resolve("hello world");
}
async function test() {
const v1 = await getValue();
const v2 = await testAsync();
console.log(v1, v2);// 123 hello world
}
test();
await等到結果之後
返回Promise
對象的處理結果,如果等待的不是Promise
對象,則返回值本身。
await
會在暫停async
函數,等待Promise
處理完成。
如果Promise
正常處理,則回調的resolve
函數參數作爲await
的值,繼續執行async
函數。
如果Promise
處理異常,await
會把Promise的異常原因拋出。
爲啥要使用async/await
反正都是處理Promise對象,爲啥不直接用.then()呢?用setTimeout模擬耗時的異步操作。
function mockApi() {
return new Promise((resolve) => {
setTimeout(() => resolve("hello world"), 1000);
});
}
// then寫法
mockApi().then(v => {
console.log("then", v);
})
// async/await寫法
async function test() {
const v = await mockApi();
console.log(v);
}
test();
async/await
反而要多寫一點代碼,繁重的工作雪上加霜了。😂😂😂😂😂
不要着急,脫褲子肯定不是爲了...
單一的Promise
鏈並不能發現async/await
的妙用😏,當遇到多個Promise
組成的then
鏈時,你會發現async/await
就是救世主。
試試看,一個業務處理分成多個步驟,每一步都是異步 的,而且每一步都依賴前一步的結果。
setTimeout
受累一下😙😙😙
/**
* 傳入參數value,表示這個函數執行的時間
* 執行結果增加1000,用於下一步
* @param {*} value 時間
* @returns 時間+1000ms
*/
function mockApi(value) {
return new Promise((resolve) => {
setTimeout(() => resolve(value + 1000), value);
});
}
function step1(value) {
console.log(`step1 with ${value}`);
return mockApi(value);
}
function step2(value) {
console.log(`step2 with ${value}`);
return mockApi(value);
}
function step3(value) {
console.log(`step3 with ${value}`);
return mockApi(value);
}
// then寫法
function testThen() {
console.time("testThen");
const time1 = 300;
step1(time1).then((time2) => {
step2(time2).then((time3) => {
step3(time3).then((result) => {
console.log(`result is ${result}`); // 我已經暈了😵😵😵😵
console.timeEnd("testThen");
});
});
});
}
testThen();
// step1 with 300
// step2 with 1300
// step3 with 2300
// result is 3300
// testThen: 3921.948ms
// async/await寫法
async function testAsync() {
console.time("testAsync");
const time1 = 300;
const time2 = await step1(time1);
const time2 = await step3(time1);
const result = await step3(time1);
console.log(`result is ${result}`); // YYDS
console.timeEnd("testAsync");
}
testAsync();
async/await
有多清晰,不用多說了吧。
附庸風雅😳😳😳
梅花引 荊溪阻雪 蔣捷
白鷗問我泊孤舟
是身留?是心留?
心若留時,何事鎖眉頭?
風拍小簾燈暈舞
對閒影,冷清清,憶舊遊。
舊遊舊遊今在不?
花外樓,柳下舟。
夢也夢也,夢不到,寒水空流。
漠漠黃雲,溼透木棉裘。
都道無人愁似我
今夜雪,有梅花,似我愁。