async 和 await

1、前言

async函數(shù),也就是我們常說的async/await,是在ES2017(ES8)引入的新特性,主要目的是為了簡化使用基于Promise的API時所需的語法。async和await關(guān)鍵字讓我們可以用一種更簡潔的方式寫出基于Promise的異步行為,而無需刻意地鏈式調(diào)用Promise。

2、詳解

async表示函數(shù)里有異步操作,await表示緊跟在后面的表達式需要等待結(jié)果。需要注意的是await關(guān)鍵字只在async函數(shù)內(nèi)有效,如果在async函數(shù)體之外使用它,會拋出語法錯誤。

2.1、async

async函數(shù)返回一個 Promise對象,可以使用then方法添加回調(diào)函數(shù)。只要使用async,不管函數(shù)內(nèi)部返回的是不是Promise對象,都會被包裝成Promise對象。

話不多說,上代碼看效果:

2.1.1、函數(shù)返回非Promise對象

asyncfunctiontestAsync() {

return"hello async";

}

const result =testAsync();

console.log(result);

可以看出函數(shù)直接返回字符串時,返回的是Promise對象,相當于直接通過Promise.resolve()將字符串封裝為Promise對象。如果函數(shù)沒有返回值時,PromiseResult結(jié)果為undefined。

2.1.2、函數(shù)返回Promise對象

async function testAsync() {

return new Promise(function(resolve, reject) {

if(true) {

resolve('resolve return')

}else{

reject('reject return')

}

}

)}

console.log(testAsync());

可以看出返回的也是Promise對象。

2.2、await

await關(guān)鍵字可以跟在任意變量或者表達式之前,但通常await后面會跟一個異步過程。await使用時,會阻塞后續(xù)代碼執(zhí)行。我們先拋開async,單獨談await。

由于await只能在async標識的函數(shù)內(nèi)使用,以下例子請在瀏覽器控制臺執(zhí)行看效果。

function testAsync() {

return new Promise(

function(resolve, reject) {

setTimeout(function() {

if(true) {

console.log('請求中...')

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í)行完后,才會執(zhí)行后續(xù)代碼。您也可以嘗試一下把testAsync前的await去掉,看看跟加上await時有啥區(qū)別。

2.3、async、await結(jié)合使用

上面我們知道了await會阻塞后續(xù)代碼運行,那怎么解決這個問題呢?就需要用到async,使用async后,函數(shù)執(zhí)行時,一旦遇到await就會先返回一個Promise對象,等到await后的操作完成后,再接著執(zhí)行async函數(shù)體內(nèi)的語句。

先上語法:

async function函數(shù)名() {

await XXX;?

}

上示例代碼:

function testAsync() {

return new Promise(

function(resolve, reject) {

setTimeout(function() {

if(true) {

console.log('請求中...')

resolve('resolve return')

}else{

reject('reject return')}

},2000)}

)}

function testAsync2() {

return new Promise(

function(resolve, reject) {

setTimeout(function() {

if(true) {

console.log('請求中2...')

resolve('resolve return2')

}else{reject('reject return2')}

},2000)})}

async functiontest() {

console.log('test開始...');

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());

上圖可以看出遇到第一個await后,立即返回了Promise對象,然后再按順序去執(zhí)行testAsync函數(shù),等待testAsync函數(shù)執(zhí)行后再去執(zhí)行testAsync2函數(shù)。還可以看出async函數(shù)可以簡化Promise的語法,以往我們需要使用.then去處理回調(diào),現(xiàn)在我們可以使用await像寫同步代碼一樣去寫異步代碼。

我們再升級一下,在上面的基礎上再加入兩個普通函數(shù):

function fun1() {

return'函數(shù)1'

}

functionfun2() {

return'函數(shù)2'

}

functionfun3() {

console.log(fun1());

console.log(test());// async/await函數(shù)

console.log(fun2());

}

console.log(fun3());

我們先梳理一下函數(shù)的執(zhí)行過程,

1、先執(zhí)行函數(shù)1

2、進入test函數(shù)并輸出開始

3、在test函數(shù)中遇到await,立即返回Promise對象

4、執(zhí)行函數(shù)2

5、執(zhí)行test函數(shù)中的testAsync方法

6、等到test函數(shù)中的testAsync方法執(zhí)行完后,繼續(xù)執(zhí)行testAsync2方法

7、test函數(shù)結(jié)束

可以看出,async函數(shù)在遇到await后會立即返回Promise對象,繼續(xù)執(zhí)行async函數(shù)外部后續(xù)邏輯,async函數(shù)內(nèi)部會被await阻塞并按順序執(zhí)行代碼邏輯。

2.4、async、await異常處理

await后面的函數(shù)是有可能出現(xiàn)異常的,所以最好把await命令放在try...catch代碼塊中。如果await后是Promise對象,也可以使用.catch進行捕獲。

// 第一種寫法async function myFunction() {

try{

await something();??

?}catch(err) {

console.log(err);?

?}?

}// 第二種寫法async function myFunction() {await somethingPromise() .catch(function(err) {console.log(err);? }); }

3、總結(jié)

async函數(shù)在遇到await后會立即返回Promise對象,繼續(xù)執(zhí)行async函數(shù)外部邏輯,async函數(shù)內(nèi)部會被await阻塞并按順序執(zhí)行代碼邏輯。

可以使用try...catch或.catch對async函數(shù)進行異常處理。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容