深入淺出探究JavaScript中的async與await
1、前言
async函數(shù),也就是我們常說(shuō)的async/await,是在ES2017(ES8)引入的新特性,主要目的是為了簡(jiǎn)化使用基于Promise的API時(shí)所需的語(yǔ)法。async和await關(guān)鍵字讓我們可以用一種更簡(jiǎn)潔的方式寫(xiě)出基于Promise的異步行為,而無(wú)需刻意地鏈?zhǔn)秸{(diào)用Promise。
2、詳解
async表示函數(shù)里有異步操作,await表示緊跟在后面的表達(dá)式需要等待結(jié)果。需要注意的是await關(guān)鍵字只在async函數(shù)內(nèi)有效,如果在async函數(shù)體之外使用它,會(huì)拋出語(yǔ)法錯(cuò)誤。
2.1、async
async函數(shù)返回一個(gè) Promise對(duì)象,可以使用then方法添加回調(diào)函數(shù)。只要使用async,不管函數(shù)內(nèi)部返回的是不是Promise對(duì)象,都會(huì)被包裝成Promise對(duì)象。
話不多說(shuō),上代碼看效果:
2.1.1、函數(shù)返回非Promise對(duì)象
async function testAsync() {
return "hello async";
}
const result = testAsync();
console.log(result);

可以看出函數(shù)直接返回字符串時(shí),返回的是Promise對(duì)象,相當(dāng)于直接通過(guò)Promise.resolve()將字符串封裝為Promise對(duì)象。如果函數(shù)沒(méi)有返回值時(shí),PromiseResult結(jié)果為undefined。
2.1.2、函數(shù)返回Promise對(duì)象
async function testAsync() {
return new Promise(function(resolve, reject) {
if (true) {
resolve('resolve return')
} else {
reject('reject return')
}
})
}
console.log(testAsync());

可以看出返回的也是Promise對(duì)象。
2.2、await
await關(guān)鍵字可以跟在任意變量或者表達(dá)式之前,但通常await后面會(huì)跟一個(gè)異步過(guò)程。await使用時(shí),會(huì)阻塞后續(xù)代碼執(zhí)行。我們先拋開(kāi)async,單獨(dú)談await。
由于await只能在async標(biāo)識(shí)的函數(shù)內(nèi)使用,以下例子請(qǐng)?jiān)跒g覽器控制臺(tái)執(zhí)行看效果。
function testAsync() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
if (true) {
console.log('請(qǐng)求中...')
resolve('resolve return')
} else {
reject('reject return')
}
}, 2000)
})
}
var result = await testAsync();
var result1 = await "testAsync后執(zhí)行";
console.log(result);
console.log(result1);

可以看出,使用了await后,必須得等testAsync方法執(zhí)行完后,才會(huì)執(zhí)行后續(xù)代碼。您也可以嘗試一下把testAsync前的async去掉,看看跟加上await時(shí)有啥區(qū)別。
2.3、async、await結(jié)合使用
上面我們知道了await會(huì)阻塞后續(xù)代碼運(yùn)行,那怎么解決這個(gè)問(wèn)題呢?就需要用到async,使用async后,函數(shù)執(zhí)行時(shí),一旦遇到await就會(huì)先返回一個(gè)Promise對(duì)象,等到await后的操作完成后,再接著執(zhí)行async函數(shù)體內(nèi)的語(yǔ)句。
先上語(yǔ)法:
async function 函數(shù)名() {
await XXX;
}
上示例代碼:
function testAsync() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
if (true) {
console.log('請(qǐng)求中...')
resolve('resolve return')
} else {
reject('reject return')
}
}, 2000)
})
}
function testAsync2() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
if (true) {
console.log('請(qǐng)求中2...')
resolve('resolve return2')
} else {
reject('reject return2')
}
}, 2000)
})
}
async function test() {
console.log('test開(kāi)始...');
var value1 = await testAsync();
console.log(value1);
var value2 = await testAsync2();
console.log(value2);
var value3 = await 'test結(jié)束...';
console.log(value3);
}
console.log(test());

上圖可以看出遇到第一個(gè)await后,立即返回了Promise對(duì)象,然后再按順序去執(zhí)行testAsync函數(shù),等待testAsync函數(shù)執(zhí)行后再去執(zhí)行testAsync2函數(shù)。還可以看出async函數(shù)可以簡(jiǎn)化Promise的語(yǔ)法,以往我們需要使用.then去處理回調(diào),現(xiàn)在我們可以使用await像寫(xiě)同步代碼一樣去寫(xiě)異步代碼。
我們?cè)偕?jí)一下,在上面的基礎(chǔ)上再加入兩個(gè)普通函數(shù):
function fun1() {
return '函數(shù)1'
}
function fun2() {
return '函數(shù)2'
}
function fun3() {
console.log(fun1());
console.log(test()); // async/await函數(shù)
console.log(fun2());
}
console.log(fun3());

我們先梳理一下函數(shù)的執(zhí)行過(guò)程,
1、先執(zhí)行函數(shù)1
2、進(jìn)入test函數(shù)并輸出開(kāi)始
3、在test函數(shù)中遇到await,立即返回Promise對(duì)象
4、執(zhí)行函數(shù)2
5、執(zhí)行test函數(shù)中的testAsync方法
6、等到test函數(shù)中的testAsync方法執(zhí)行完后,繼續(xù)執(zhí)行testAsync2方法
7、test函數(shù)結(jié)束
可以看出,async函數(shù)在遇到await后會(huì)立即返回Promise對(duì)象,繼續(xù)執(zhí)行async函數(shù)外部后續(xù)邏輯,async函數(shù)內(nèi)部會(huì)被await阻塞并按順序執(zhí)行代碼邏輯。
2.4、async、await異常處理
await后面的函數(shù)是有可能出現(xiàn)異常的,所以最好把a(bǔ)wait命令放在try...catch代碼塊中。如果await后是Promise對(duì)象,也可以使用.catch進(jìn)行捕獲。
// 第一種寫(xiě)法
async function myFunction() {
try {
await something();
} catch (err) {
console.log(err);
}
}
// 第二種寫(xiě)法
async function myFunction() {
await somethingPromise()
.catch(function (err) {
console.log(err);
});
}
3、總結(jié)
async函數(shù)在遇到await后會(huì)立即返回Promise對(duì)象,繼續(xù)執(zhí)行async函數(shù)外部邏輯,async函數(shù)內(nèi)部會(huì)被await阻塞并按順序執(zhí)行代碼邏輯。
可以使用try...catch或.catch對(duì)async函數(shù)進(jìn)行異常處理。
到此這篇關(guān)于深入淺出探究JavaScript中的async與await的文章就介紹到這了,更多相關(guān)JavaScript async await內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
await 錯(cuò)誤捕獲實(shí)現(xiàn)方式源碼解析
這篇文章主要為大家介紹了await 錯(cuò)誤捕獲實(shí)現(xiàn)方式源碼示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
微信小程序報(bào)錯(cuò):this.setData is not a function的解決辦法
這篇文章主要介紹了微信小程序報(bào)錯(cuò):this.setData is not a function的解決辦法的相關(guān)資料,希望通過(guò)本文能幫助到大家解決這樣類似的問(wèn)題,需要的朋友可以參考下2017-09-09
微信小程序 彈框和模態(tài)框?qū)崿F(xiàn)代碼
這篇文章主要介紹了微信小程序 彈框和模態(tài)框?qū)崿F(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03
微信小程序 圖片寬度自適應(yīng)的實(shí)現(xiàn)
這篇文章主要介紹了微信小程序 圖片寬度自適應(yīng)的實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2017-04-04
TypeScript新語(yǔ)法之infer?extends示例詳解
這篇文章主要為大家介紹了TypeScript新語(yǔ)法之infer?extends示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
Dragonfly P2P 傳輸協(xié)議優(yōu)化代碼解析
這篇文章主要為大家介紹了Dragonfly P2P 傳輸協(xié)議優(yōu)化代碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
JS數(shù)組方法some、every和find的使用詳情
這篇文章 要給大家介紹的是JS數(shù)組方法some、every和find的使用的一些相關(guān)資料,感興趣的小伙伴一起來(lái)學(xué)習(xí)吧2021-09-09
Qiankun Sentry 監(jiān)控異常上報(bào)無(wú)法自動(dòng)區(qū)分項(xiàng)目解決
這篇文章主要為大家介紹了Qiankun Sentry 監(jiān)控異常上報(bào)無(wú)法自動(dòng)區(qū)分項(xiàng)目解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11

