NodeJs中怎么使用async和await處理異步,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
場(chǎng)景
遠(yuǎn)古時(shí)代
我們?cè)诰帉慹xpress后臺(tái),經(jīng)常要有許多異步IO的處理。在遠(yuǎn)古時(shí)代,我們都是用chunk函數(shù)處理,也就是我們最熟悉的那種默認(rèn)第一個(gè)參數(shù)是error
的函數(shù)。我們來模擬一個(gè)Mongo數(shù)據(jù)庫的操作,感受一下。
mongoDb.open(function(err, db){ if(!err){ db.collection("users", function(err, collection){ if(!err){ let person = {name: "yika", age: 20}; collection.insert(person, function(err, result){ if(!err){ console.log(result); } }); } }) } });
這個(gè)也就是被我們所詬病的callback hell
,一堆橫向金字塔,如果將回調(diào)拆分成函數(shù),則會(huì)變得非常支離破碎。為了防止到惡心到大家,我甚至沒有寫關(guān)于錯(cuò)誤的處理,正常來說,每一個(gè)異步的操作都需要都它的error
進(jìn)行相應(yīng)的顯示或處理的。
Promise時(shí)代
后來進(jìn)入了好一點(diǎn)的時(shí)代就是Promise,我們也可以稱作鏈?zhǔn)讲僮?。關(guān)于Promise,我也是之前有專門寫過一系列的博文,有興趣可以回頭翻一下。這里來看看,將以上改寫之后的狀況。
let person = {name: "yika"}; mongoDb .open() .then(function(database){ return database.collection("users"); }) .then(function(collection){ return collection.insert(person); }) .then(function(result){ console.log(result); }) .catch(function(e){ throw new Error(e); })
我們可以看到,我們將金字塔已經(jīng)平鋪成一條線狀結(jié)構(gòu)了。相比之前惡心難以維護(hù)的chunk函數(shù),變成了promise函數(shù),并且錯(cuò)誤的處理也變得十分優(yōu)雅。但是我們?nèi)匀徊豢珊鲆暷承﹩栴},例如我們必須忍受各個(gè)邏輯被一個(gè)又一個(gè)的then()
包裹起來,每一個(gè)函數(shù)都有其獨(dú)立的作用域,如果為了共享某個(gè)數(shù)據(jù)就必須掛在最外層,最重要的還是,它與我們熟悉的同步編程仍然有差別。
Generator時(shí)代
TJ大神,借著ES6的Generator迭代器,最早實(shí)現(xiàn)了異步編程同步化的功能,也就是最為我們所熟知的co
庫。我們通過co(function *(){})
可以使函數(shù)內(nèi)部通過迭代器來控制。而co
在這里則是充當(dāng)了啟動(dòng)器的角色。關(guān)于Generator和co我在之前的博文也同樣說過。
let co = require("co"); co(function *(){ let db, collection, result; let person = {name: "yika"}; try{ db = yield mongoDb.open(); collection = yield db.collection("users"); result = yield collection.insert(person); }catch(e){ console.error(e.message); } console.log(result); });
我們已經(jīng)非常接近同步編程了,在co包裹的函數(shù)內(nèi)部,只有一個(gè)異步執(zhí)行完畢,才會(huì)繼續(xù)執(zhí)行下面的代碼。并且錯(cuò)誤的處理也是通過try and catch
進(jìn)行實(shí)現(xiàn)的。不過我們不得不承認(rèn)的是,迭代器終究不是為異步而存在的。里面的yield
和*
的語義也并不代表的就是異步函數(shù)標(biāo)志。并且迭代器是需要co去驅(qū)動(dòng)的,它和我們想象中的函數(shù)多少有一點(diǎn)點(diǎn)不同。
async/await時(shí)代
我們關(guān)注到ES7的async/await,才發(fā)現(xiàn)這才是我們想要的!我們將上面的代碼小小改寫一下。
async function insertData(person){ let db, collection, result; try{ db = await mongoDb.open(); collection = await db.collection("users"); result = await collection.insert(person); }catch(e){ console.error(e.message); } console.log(result); } insertData({name: "yika"});
我們可以看到inserData
是一個(gè)真正的函數(shù),是我們可以直接去調(diào)用而無需啟動(dòng)器驅(qū)動(dòng)的。當(dāng)然內(nèi)部我們也可以感受到處理yield
變成了await
以外,并沒有很大區(qū)別。async/await,更符合我們異步編程的語義。
那么問題來了,how to use it?
使用
我們一開始就說過,babel已經(jīng)支持async的transform了,所以我們使用的時(shí)候引入babel就行。當(dāng)然server端和browser端,可以有不同的處理方法。在開始之前我們需要引入以下的package,preset-stage-3里就有我們需要的async/await的編譯文件。
$ npm install babel-core --save $ npm install babel-preset-es2015 --save $ npm install babel-preset-stage-3 --save
Browser端
Babel一開始的出現(xiàn)就是為了讓舊瀏覽器也能支持新的ES6特性,提升我們的開發(fā)體驗(yàn)。所以在Babel一開始就是可以通過babel-cli終端進(jìn)行編譯的?;蛘咭隻abel文件在瀏覽器端進(jìn)行編譯。當(dāng)然這些都不是我最推薦的,所以我就帶過不說啦。在前端靜態(tài)資源配置里,webpack是現(xiàn)在比較好的解決方案,它支持靜態(tài)資源的模塊依賴,打包合并,還有語言的預(yù)處理,當(dāng)然在這里我們就是指babel的處理。
// webpack.config.js // 省略上面的文件輸入輸出的配置,直接看模塊加載器的配置 module: { loaders: [ { test: /\.js$/, exclude: /(node_modules|bower_components)/, loader: "babel", query: { presets: ['es2015', 'stage-3'] } }, ] }
這樣我們就可以愉快的使用了。
Server端
相對(duì)來說,后端比前端需要處理的異步IO地方多得多,也是更加需要這個(gè)。那我們?cè)赟erver端又如何引入babel呢?
其實(shí)最簡(jiǎn)單也是最麻煩的方法就是,直接把js文件通過babel編譯出新的文件再來使用。當(dāng)然也就免不了冗余文件了,眼不見心不煩,還是換一個(gè)方法吧。
我們使用官方提供的require hook方法,顧名思義就是通過require進(jìn)來后,接下來的文件進(jìn)行require的時(shí)候都會(huì)經(jīng)過Babel的處理。因?yàn)槲覀冎繡ommonJs是同步的模塊依賴,所以也是可行的方法。我們需要多一個(gè)用于啟動(dòng)的js文件,一個(gè)真正執(zhí)行程序的js文件。
// index.js // 用于引入babel,并且啟動(dòng)app.js require("babel-core/register"); require("./app.js");
配置完hook之后,我們就配置babel的.babelrc文件,它是一個(gè)json格式的文件。es2015看情況配置,如果是已經(jīng)是Node5.0版本,就無需再進(jìn)行編譯。
{ "presets": ["stage-3", "es2015"] }
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司的支持。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、網(wǎng)站設(shè)計(jì)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。
分享題目:NodeJs中怎么使用async和await處理異步-創(chuàng)新互聯(lián)
文章路徑:http://chinadenli.net/article28/dgpicp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、虛擬主機(jī)、網(wǎng)站設(shè)計(jì)公司、面包屑導(dǎo)航、Google、網(wǎng)頁設(shè)計(jì)公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容