在最開(kāi)始學(xué)習(xí)ES6的Promise時(shí),曾寫過(guò)一篇博文 《promise和co搭配生成器函數(shù)方式解決js代碼異步流程的比較》 ,文章中對(duì)比了使用Promise和co模塊搭配生成器函數(shù)解決js異步的異同。
在文章末尾,提到了ES7的async和await,只是當(dāng)時(shí)只是簡(jiǎn)單的提了一下,并未做深入探討。
在前兩個(gè)月發(fā)布的Nodejs V7中,已添加了對(duì)async和await的支持,今天就來(lái)對(duì)這個(gè)東東做一下深入的探究。以更加優(yōu)雅的方法寫異步代碼。
async/await是什么
async/await可以說(shuō)是co模塊和生成器函數(shù)的語(yǔ)法糖。用更加清晰的語(yǔ)義解決js異步代碼。
熟悉co模塊的同學(xué)應(yīng)該都知道,co模塊是TJ大神寫的一個(gè)使用生成器函數(shù)來(lái)解決異步流程的模塊,可以看做是生成器函數(shù)的執(zhí)行器。而async/await則是對(duì)co模塊的升級(jí),內(nèi)置生成器函數(shù)的執(zhí)行器,不再依賴co模塊。同時(shí),async返回的是Promise。
從上面來(lái)看,不管是co模塊還是async/await,都是將Promise作為最基礎(chǔ)的單元,對(duì)Promise不很了解的同學(xué)可以先深入了解一下Promise。
對(duì)比Promise,co,async/await
下面我們使用一個(gè)簡(jiǎn)單的例子,來(lái)對(duì)比一下三種方式的異同,以及取舍。
我們采用mongodb的nodejs驅(qū)動(dòng),查詢mongodb數(shù)據(jù)庫(kù)作為例子,原因是mongodb的js驅(qū)動(dòng)已經(jīng)默認(rèn)實(shí)現(xiàn)了返回Promise,而不用我們單獨(dú)去包裝Promise了。
使用Promise鏈
MongoClient.connect(url + db_name).then(db=> { return db.collection('blogs');}).then(coll=> { return coll.find().toArray();}).then(blogs=> { console.log(blogs.length);}).catch(err=> { console.log(err);})Promise的then()方法可以返回另一個(gè)Promise,也可以返回一個(gè)同步的值,如果返回的是一個(gè)同步值,將會(huì)被包裝成一個(gè)Promise。
上面的例子中,db.collection()將返回一個(gè)同步的值,即集合對(duì)象,但是被包裝成Promise,將會(huì)透?jìng)鞯较乱粋€(gè)then()方法。
上面一個(gè)例子,是使用的Promise鏈。
先連接數(shù)據(jù)庫(kù)MongoClient.connect()返回一個(gè)Promise,然后在then()方法里獲得數(shù)據(jù)庫(kù)對(duì)象db,然后再獲取到coll對(duì)象再返回。在下一個(gè)then()方法獲得coll對(duì)象,然后進(jìn)行查詢,查詢結(jié)果返回,逐層調(diào)用then()方法,形成一個(gè)Promise鏈。
在這個(gè)Promise鏈上,如果任何一個(gè)環(huán)節(jié)出現(xiàn)異常,都會(huì)被最后的catch()捕捉到。
可以說(shuō),這個(gè)使用Promise鏈寫的代碼,比層層調(diào)用回調(diào)函數(shù)更優(yōu)雅,流程也更明確。先獲得數(shù)據(jù)庫(kù)對(duì)象,再獲得集合對(duì)象,最后查詢數(shù)據(jù)。
但是這里有個(gè)不怎么“優(yōu)雅”的問(wèn)題,在于,每一個(gè)then()方法獲取的對(duì)象,都是上一個(gè)then()方法返回的數(shù)據(jù)。而不能跨層訪問(wèn)。
什么意思,就是說(shuō)在第三個(gè)then(blogs => {})中我們只能獲取到查詢的結(jié)果blogs,而不能使用上面的db對(duì)象和coll對(duì)象。這個(gè)時(shí)候,如果要打印出blogs列表后,要關(guān)閉數(shù)據(jù)庫(kù)db.close()怎么辦?
|
新聞熱點(diǎn)
疑難解答
圖片精選