深入淺出探究JavaScript中的async與await
1、前言
async函數(shù),也就是我們常說的async/await,是在ES2017(ES8)引入的新特性,主要目的是為了簡化使用基于Promise的API時(shí)所需的語法。async
和await
關(guān)鍵字讓我們可以用一種更簡潔的方式寫出基于Promise的異步行為,而無需刻意地鏈?zhǔn)秸{(diào)用Promise。
2、詳解
async表示函數(shù)里有異步操作,await表示緊跟在后面的表達(dá)式需要等待結(jié)果。需要注意的是await
關(guān)鍵字只在async函數(shù)內(nèi)有效,如果在async函數(shù)體之外使用它,會拋出語法錯(cuò)誤。
2.1、async
async函數(shù)返回一個(gè) Promise對象,可以使用then方法添加回調(diào)函數(shù)。只要使用async,不管函數(shù)內(nèi)部返回的是不是Promise對象,都會被包裝成Promise對象。
話不多說,上代碼看效果:
2.1.1、函數(shù)返回非Promise對象
async function testAsync() { return "hello async"; } const result = testAsync(); console.log(result);
可以看出函數(shù)直接返回字符串時(shí),返回的是Promise對象,相當(dāng)于直接通過Promise.resolve()將字符串封裝為Promise對象。如果函數(shù)沒有返回值時(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)鍵字可以跟在任意變量或者表達(dá)式之前,但通常await后面會跟一個(gè)異步過程。await使用時(shí),會阻塞后續(xù)代碼執(zhí)行。我們先拋開async,單獨(dú)談await。
由于await只能在async標(biāo)識的函數(shù)內(nèi)使用,以下例子請?jiān)跒g覽器控制臺執(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前的async去掉,看看跟加上await時(shí)有啥區(qū)別。
2.3、async、await結(jié)合使用
上面我們知道了await會阻塞后續(xù)代碼運(yùn)行,那怎么解決這個(gè)問題呢?就需要用到async,使用async后,函數(shù)執(zhí)行時(shí),一旦遇到await就會先返回一個(gè)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 function test() { 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());
上圖可以看出遇到第一個(gè)await后,立即返回了Promise對象,然后再按順序去執(zhí)行testAsync函數(shù),等待testAsync函數(shù)執(zhí)行后再去執(zhí)行testAsync2函數(shù)。還可以看出async函數(shù)可以簡化Promise的語法,以往我們需要使用.then去處理回調(diào),現(xiàn)在我們可以使用await像寫同步代碼一樣去寫異步代碼。
我們再升級一下,在上面的基礎(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í)行過程,
1、先執(zhí)行函數(shù)1
2、進(jìn)入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)異常的,所以最好把a(bǔ)wait命令放在try...catch代碼塊中。如果await后是Promise對象,也可以使用.catch進(jìn)行捕獲。
// 第一種寫法 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ù)進(jìn)行異常處理。
到此這篇關(guān)于深入淺出探究JavaScript中的async與await的文章就介紹到這了,更多相關(guān)JavaScript async await內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序 es6-promise.js封裝請求與處理異步進(jìn)程
這篇文章主要介紹了微信小程序 es6-promise.js封裝請求與處理異步進(jìn)程的相關(guān)資料,需要的朋友可以參考下2017-06-06JavaScript前端實(shí)用的工具函數(shù)封裝
這篇文章主要為大家介紹了JavaScript前端實(shí)用的一些工具函數(shù)的封裝,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07