JS中的async與await異步編程及await使用陷阱
ECMA2017中新加入了兩個(gè)關(guān)鍵字async與await
簡單來說它們是基于promise之上的的語法糖,可以讓異步操作更加地簡單明了
首先我們需要用async關(guān)鍵字,將函數(shù)標(biāo)記為異步函數(shù)
async function f() { } f()
異步函數(shù)就是指:返回值為promise對象的函數(shù)
比如之前用到的fetch()就是一個(gè)異步函數(shù),返回的是promise
在異步函數(shù)中,我們可以調(diào)用其他的異步函數(shù),不過我們不再需要使用then,而是使用一個(gè)await。
await會(huì)等待Promise完成之后直接返回最終結(jié)果
所以這里的response已經(jīng)是一個(gè)服務(wù)器返回的響應(yīng)數(shù)據(jù)了
async function f() { const response = await fetch("http://....") } f()
雖然await看上去會(huì)暫停函數(shù)的執(zhí)行,但在等待的過程中,js同樣可以處理其他的任務(wù)
這是因?yàn)閍wait底層是基于promise與事件循環(huán)(event loop)機(jī)制實(shí)現(xiàn)的
await使用時(shí)的陷阱:
1、第一個(gè)陷阱
比如:我們分別去await這兩個(gè)異步操作
async function f() { const a = fetch("http://..../post/1") const b = fetch("http://..../post/2") } f()
雖然不存在邏輯錯(cuò)誤
但這樣會(huì)打破這兩個(gè)fetch()操作的并行
因?yàn)槲覀儠?huì)等到第一個(gè)任務(wù)執(zhí)行完成之后才開始執(zhí)行第二個(gè)任務(wù)
這里更高效的方法是將所有的Promise用Promise.all組合起來,然后再去await:
修改之后的執(zhí)行效率會(huì)直接提升一倍
async function f() { const promiseA = fetch("http://..../post/1") const promiseB = fetch("http://..../post/2") const [a, b] = await Promise.all([promiseA,promiseB]) } f()
2、第二個(gè)陷阱
如果我們需要在循環(huán)中執(zhí)行異步操作,是不能夠直接調(diào)用forEach或者map這一類方法的,盡管我們在回調(diào)函數(shù)中寫了await也不行。
因?yàn)檫@里的forEach會(huì)立即返回,它并不會(huì)等到所有的異步操作都執(zhí)行完畢
async function f() { [1,2,3].forEach(async (i) => { await someAsyncOperation(); }) console.log("done") } f()
如果我們希望等待循環(huán)中的異步操作都一一完成之后才繼續(xù)執(zhí)行
我們應(yīng)當(dāng)使用傳統(tǒng)的for循環(huán)
async function f() { for( let i of [1,2,3]){ await someAsyncOperation(); } console.log("done") } f()
如果我們希望所有的程序并發(fā)執(zhí)行,一種更炫酷的寫法就是使用for await
這里的for循環(huán)依然會(huì)等到所有的異步操作都完成之后才會(huì)繼續(xù)向后執(zhí)行
3、第三個(gè)陷阱
我們不能在全局或者普通函數(shù)中直接使用await關(guān)鍵字
await只能用在異步函數(shù)(async function)中
如果我們想要在最外層中使用await,那么需要先定義一個(gè)異步函數(shù):
使用await async可以讓我們寫出更清晰,更容易理解的異步代碼
到此這篇關(guān)于async與await異步編程的文章就介紹到這了,更多相關(guān)async與await異步編程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS+CSS實(shí)現(xiàn)的拖動(dòng)分頁效果實(shí)例
這篇文章主要介紹了JS+CSS實(shí)現(xiàn)的拖動(dòng)分頁效果,可實(shí)現(xiàn)鼠標(biāo)拖動(dòng)頁面翻轉(zhuǎn)到上一頁或下一頁的功能,涉及javascript操作頁面元素與css樣式的相關(guān)技巧,需要的朋友可以參考下2015-05-05基于es6三點(diǎn)運(yùn)算符的使用方法(實(shí)例講解)
下面小編就為大家?guī)硪黄谌c(diǎn)運(yùn)算符的使用方法(實(shí)例講解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10詳解js產(chǎn)生對象的3種基本方式(工廠模式,構(gòu)造函數(shù)模式,原型模式)
本篇文章主要介紹了js產(chǎn)生對象的3種基本方式(工廠模式,構(gòu)造函數(shù)模式,原型模式) ,具有一定的參考價(jià)值,有興趣的可以了解一下2017-01-01ES6中的Javascript解構(gòu)的實(shí)現(xiàn)
這篇文章主要介紹了ES6中的Javascript解構(gòu)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10