async
異步關(guān)鍵字土匀,一般我們把這個(gè)關(guān)鍵字寫在函數(shù)前,用于表示函數(shù)是一個(gè)異步函數(shù)形用, 異步函數(shù)也就意味著該函數(shù)的執(zhí)行不會阻塞后面代碼的執(zhí)行就轧。
聲明async函數(shù)的幾個(gè)方法:
- 普通的函數(shù)聲明
async function A(){}
- 聲明一個(gè)函數(shù)表達(dá)式
let A = async function(){}
- async形式的箭頭函數(shù)
let A = async ()=>{}
異步函數(shù)調(diào)用也跟普通函數(shù)調(diào)用一樣
async function A(){}
console.log(A());
console.log('雖然在后面,但是我先執(zhí)行');
我們可以看到田度,異步函數(shù)是不會阻塞下面代碼的執(zhí)行妒御,并且異步函數(shù)返回了一個(gè)promise 對象,promise 對象是可以返回值和拋出錯(cuò)誤的:
async function A(val){
if (val) {
return '123'
} else {
throw '錯(cuò)誤'
}
}
console.log(A(true));
console.log(A(false));
再使用then和catch捕獲返回值和錯(cuò)誤信息镇饺。
await
等待關(guān)鍵字乎莉,意思是等待,等待后面的表達(dá)式執(zhí)行完再繼續(xù)執(zhí)行下面的代碼奸笤,這個(gè)作用的好處就是能大大減少回調(diào)地獄惋啃。后面可以放置任何表達(dá)式,但是更多的是放一個(gè)返回promise 對象的表達(dá)式监右。注意await 關(guān)鍵字只能放到async 函數(shù)里面边灭。
舉個(gè)例子,有個(gè)場景健盒,需要調(diào)用a方法調(diào)取接口數(shù)據(jù)绒瘦,等到獲取數(shù)據(jù)之后再執(zhí)行b方法,如果這時(shí)候不使用await扣癣,那就是需要編寫回調(diào)方法椭坚,當(dāng)我們再多幾步這樣的操作就很容易陷入回調(diào)地獄。
a(() => {
b(() => {
c();
});
});
await a();
await b();
c();
修改代碼后確實(shí)簡潔很多搏色,但是如果濫用也很造成性能問題善茎,如果ac方法是并行的,簡單粗暴使用await會拉低整體執(zhí)行的時(shí)間频轿。
a(() => {
b();
});
c(() => {
d();
});
// 改為
await a();
b();
await c();
d();
改了之后雖然看起來是b等待a執(zhí)行完垂涯,d等待c執(zhí)行完,但是實(shí)際上d需要等ac都執(zhí)行完才能執(zhí)行航邢,白白增加了等待的時(shí)長耕赘。
這種情況需要使用Promise.all()或者把兩個(gè)執(zhí)行完全隔離開來。
所以膳殷,await的使用也需要考慮具體的執(zhí)行邏輯操骡。
我們再來看一個(gè)串行并行的情況:
async function asyncAwaitFn(str) {
return await new Promise((resolve, reject) => {
setTimeout(() => {
resolve(str)
}, 1000);
})
}
const serialFn = async () => { //串行執(zhí)行
console.time('test')
console.log(await asyncAwaitFn('string 1'));
console.log(await asyncAwaitFn('string 2'));
console.timeEnd('test')
}
serialFn();
async function asyncAwaitFn(str) {
return await new Promise((resolve, reject) => {
setTimeout(() => {
resolve(str)
}, 1000);
})
}
const zhix= async () => { //并行執(zhí)行
console.time('zhix')
const test1 = asyncAwaitFn('string 1');
const test2 = asyncAwaitFn('string 2')
//直接打印
console.log(await test1)
console.log(await test2)
console.timeEnd('zhix')
}
zhix()
相比串行,并行執(zhí)行的效率快了差不多一倍。如果多個(gè)串行執(zhí)行改為并行册招,能大大提升執(zhí)行速度岔激。