詳解node Async/Await 更好的異步編程解決方案
一、異步編程的終極解決方案
前幾天寫過關(guān)于 javascript 異步操作的文章《Javascript Promise 詳解》. 最近在學(xué)習(xí) Puppeteer 的時(shí)候又發(fā)現(xiàn)另一種異步編程解決方案:Async/Await.
異步操作是 JavaScript 編程的麻煩事,麻煩到一直有人提出各種各樣的方案,試圖解決這個(gè)問題。 從最早的回調(diào)函數(shù),到 Promise 對(duì)象,再到 Generator 函數(shù),每次都有所改進(jìn),但又讓人覺得不徹底。 它們都有額外的復(fù)雜性,都需要理解抽象的底層運(yùn)行機(jī)制。
在 Async 函數(shù)出來(lái)之后,有人認(rèn)為它是異步編程的最終解決方案。因?yàn)橛辛?Async/Await 之后,你根本就不用關(guān)心是它是不是異步編程。
二、基本用法
async 函數(shù)返回一個(gè) Promise 對(duì)象,可以使用 then 方法添加回調(diào)函數(shù)。 當(dāng)函數(shù)執(zhí)行的時(shí)候,一旦遇到 await 就會(huì)先返回,等到觸發(fā)的異步操作完成,再接著執(zhí)行函數(shù)體內(nèi)后面的語(yǔ)句。
下面是一個(gè)栗子:
var sleep = function (time) { return new Promise(function (resolve, reject) { setTimeout(function () { resolve(); }, time); }) }; var start = async function () { // 在這里使用起來(lái)就像同步代碼那樣直觀 console.log('start'); await sleep(3000); console.log('end'); }; start();
執(zhí)行上面的代碼,你會(huì)發(fā)現(xiàn),控制臺(tái)先輸出start,稍等3秒后,輸出了end。
三、注意事項(xiàng)
1、await 命令只能用在 async 函數(shù)之中,如果用在普通函數(shù),就會(huì)報(bào)錯(cuò)。
async function dbFuc(db) { let docs = [{}, {}, {}]; // 報(bào)錯(cuò) docs.forEach(function (doc) { await db.post(doc); }); }
2、await 表示在這里等待promise返回結(jié)果了,再繼續(xù)執(zhí)行。
var sleep = function (time) { return new Promise(function (resolve, reject) { setTimeout(function () { // 返回 ‘ok' resolve('ok'); }, time); }) }; var start = async function () { let result = await sleep(3000); console.log(result); // 收到 ‘ok' };
3、await 后面跟著的應(yīng)該是一個(gè)promise對(duì)象。
如果是同步執(zhí)行的代碼沒有必要使用 await 修飾了。
4、await 只能使用在原生語(yǔ)法中,比如在 forEeach 結(jié)構(gòu)中使用 await 是無(wú)法正常工作的,必須使用 for 循環(huán)的原生語(yǔ)法。
async function dbFuc(db) { let docs = [{}, {}, {}]; // 可能得到錯(cuò)誤結(jié)果 docs.forEach(async function (doc) { await db.post(doc); }); }
如果確實(shí)希望多個(gè)請(qǐng)求并發(fā)執(zhí)行,可以使用 Promise.all 方法。
async function dbFuc(db) { let docs = [{}, {}, {}]; let promises = docs.map((doc) => db.post(doc)); let results = await Promise.all(promises); console.log(results); }
四、錯(cuò)誤捕獲
既然.then(..)不用寫了,那么.catch(..)也不用寫,可以直接用標(biāo)準(zhǔn)的try catch語(yǔ)法捕捉錯(cuò)誤。
var sleep = function (time) { return new Promise(function (resolve, reject) { setTimeout(function () { // 模擬出錯(cuò)了,返回 ‘error' reject('error'); }, time); }) }; var start = async function () { try { console.log('start'); await sleep(3000); // 這里得到了一個(gè)返回錯(cuò)誤 // 所以以下代碼不會(huì)被執(zhí)行了 console.log('end'); } catch (err) { console.log(err); // 這里捕捉到錯(cuò)誤 `error` } };
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Nodejs 和 Electron ubuntu下快速安裝過程
本文較為詳細(xì)的給大家介紹了Nodejs 和 Electron ubuntu下快速安裝過程,非常不錯(cuò),具有一定的參考借鑒價(jià)值,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-05-05nodejs項(xiàng)目windows下開機(jī)自啟動(dòng)的方法
今天小編就為大家分享一篇nodejs項(xiàng)目windows下開機(jī)自啟動(dòng)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2017-11-11Koa2中間件的作用及路由實(shí)現(xiàn)實(shí)例詳解
這篇文章主要介紹了Koa2中間件的作用及路由實(shí)現(xiàn)實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05前端如何更好的展示后端返回的十萬(wàn)條數(shù)據(jù)
這篇文章主要為大家介紹了前端如何更好的展示后端返回的十萬(wàn)條數(shù)據(jù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2021-11-11node.js中的fs.createWriteStream方法使用說(shuō)明
這篇文章主要介紹了node.js中的fs.createWriteStream方法使用說(shuō)明,本文介紹了fs.createWriteStream方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12