認(rèn)識async await 首先要從單個熟悉
-
async
官方介紹:
async function
聲明將定義一個返回AsyncFunction
對象的異步函數(shù)东涡。
個人理解:- 首先
async function
會申明定義一個異步執(zhí)行的函數(shù),無阻塞圈浇,不會阻塞后面代碼執(zhí)行 - 該函數(shù)的返回值是一個Promise對象
- 首先
執(zhí)行以下代碼
async function testAsync() {
return '茶樹菇'
}
console.log(testAsync());
/*打印結(jié)果:
Promise
result: "茶樹菇"
status: "resolved"
“Promise”原型*/
打印結(jié)果可以看出,async 可以將其后的函數(shù)執(zhí)行結(jié)果轉(zhuǎn)為Promise
對象
既然如此那以下操作也是可行的
testAsync().then(r => {
console.log(r);
});//"茶樹菇"
由以下打印結(jié)果可知async function
聲明函數(shù)是異步函數(shù)
function t() {
return new Promise(resolve => {
resolve('hah')
})
}
async function t1() {
const a = await t()
// console.log(a);
console.log('t1函數(shù)里');
}
t1()
console.log('我在t1函數(shù)調(diào)用后');
/*打印結(jié)果:
[Log] 我在t1函數(shù)調(diào)用后
[Log] t1函數(shù)里
*/
-
await
官方介紹:
await
操作符用于等待一個Promise
對象。它只能在異步函數(shù)async function
中使用娶牌。個人理解:
官方注釋await
是在等待一個Promise對象锦募,其實(shí)沒有限制摆屯,只是根據(jù)等待到的結(jié)果類型的不同有不同的操作,如果等到的就是個結(jié)果糠亩,則await
就返回這個值虐骑,如果等到的是一Promise
對象准验,則await
會阻塞后面代碼執(zhí)行,等待Promise
的結(jié)果(由于await
在async function
申明的異步執(zhí)行函數(shù)廷没,所以不會影響該函數(shù)外的其他代碼執(zhí)行糊饱,只影響內(nèi)部)
注意:如果await
等待的Promise
執(zhí)行結(jié)果除了resolve
外,還有異常處理reject
颠黎,則最好用.catch(err => err)
去接收處理異常另锋, 例const a = await t().catch(err => err)
async function testAsync1() {
return "茶樹菇";
}
function testAsync2() {
return new Promise(resolve => {
resolve('茶樹菇')
})
}
function testAsync3() {
return "茶樹菇";
}
async function testFn() {
const v1 = await testAsync1();
const v2 = await testAsync2();
const v3 = await testAsync3();
console.log(v1);//"茶樹菇"
console.log(v2);//"茶樹菇"
console.log(v3);//"茶樹菇"
//由此可見`await`等待的不一定是個`Promise`對象,也可以是個值
}
testFn();
- 為什么用
async await
盏缤,對比Promise
的優(yōu)缺點(diǎn)在哪砰蠢?
模擬個使用場景,如下代碼
需求:隨機(jī)產(chǎn)生一個1~2之間的隨機(jī)數(shù)唉铜,用延時器模擬異步操作台舱,判斷該值,如果小于一就成功潭流,大于一失敗
//用Promise實(shí)現(xiàn):
function test(resolve, reject) {
var timeOut = Math.random() * 2;
console.log('隨機(jī)數(shù)為:' + timeOut);
setTimeout(function() {
if (timeOut < 1) {
resolve('小于1, 成功')
} else {
reject('大于1,失敗')
}
}, timeOut * 1000)
}
new Promise(test).then((result) => {
console.log(result);
}).catch((reason) => {
console.log(reason);
})
打印結(jié)果:function test2() {
var timeOut = Math.random() * 2;
console.log('隨機(jī)數(shù)為:' + timeOut);
return new Promise((resolve, reject) => {
setTimeout(() => {
if (timeOut < 1) {
resolve('小于1, 成功')
} else {
reject('大于1,失敗')
}
}, 1000)
})
}
async function asyncFn() {
const v3 = await test2().catch(er => er)
console.log(v3);
}
asyncFn()
看代碼其實(shí)單一的異步處理鏈并不能看出async await
的優(yōu)勢竞惋,但是如果需要處理多個Promise
組成的處理鏈,就能看出區(qū)別
假設(shè)需求為:分布完成灰嫉,每一步都需要上一步的結(jié)果:
//每次調(diào)用時間都增加200
function logTimeOut(n) {
return new Promise(resolve => {
setTimeout(() => resolve(n + 200), n)
})
}
//第一步
function stepOne(n) {
console.log('第一步所用的時間', n);
return logTimeOut(n)
}
//第二步將第一步的結(jié)果加上200作為第二部的初始時間
function stepTow(m, n) {
console.log('第二部所用的時間',m, n);
return logTimeOut(n + m)
}
//第三步將第二步的結(jié)果加上200作為第三步的初始時間
function stepThree(k, m, n) {
console.log('第三部所用的時間', k, m, n);
return logTimeOut(k + m + n)
}
首先用Promise
實(shí)現(xiàn)
//promise實(shí)現(xiàn)
function doIt() {
console.time("doIt");
// 第一步初始時間
const time1 = 200;
stepOne(time1).then(time2 => {
return stepTow(time1, time2).then(time3 => [time1, time2, time3])
})
.then(timeArr => {
const [time1, time2, time3] = timeArr
return stepThree(time1, time2, time3)
})
.then(result => {
console.log('總共計算用時', result);
console.timeEnd('doIt')
})
}
doIt()
使用async awiat
:
// async await 實(shí)現(xiàn)
async function startIt() {
console.time("startIt")
const time1 = 200;
const time2 = await stepOne(time1)
const time3 = await stepTow(time1, time2)
const result = await stepThree(time1, time2, time3)
console.log('總共計算用時', result);
console.timeEnd('startIt')
}
打印結(jié)果:這樣對比就能明顯看出區(qū)別Promise
實(shí)現(xiàn)的代碼邏輯復(fù)雜,不清晰讼撒,不直觀浑厚,而通過async await
,可以將異步邏輯根盒,用類似于同步的代碼實(shí)現(xiàn)钳幅,簡潔明了
這是到目前為止的個人理解,轉(zhuǎn)載請標(biāo)明出處