本篇文章為大家展示了 async 函數(shù)如何在Node.js中使用,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。
我們提供的服務(wù)有:成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站、微信公眾號(hào)開(kāi)發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、南陵ssl等。為數(shù)千家企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的南陵網(wǎng)站制作公司
1 什么是 async 函數(shù)
利用 async 函數(shù),你可以把基于 Promise 的異步代碼寫(xiě)得就像同步代碼一樣。一旦你使用 async 關(guān)鍵字來(lái)定義了一個(gè)函數(shù),那你就可以在這個(gè)函數(shù)內(nèi)使用 await 關(guān)鍵字。當(dāng)一個(gè) async 函數(shù)被調(diào)用時(shí),它會(huì)返回一個(gè) Promise。當(dāng)這個(gè) async 函數(shù)返回一個(gè)值時(shí),那個(gè) Promise 就會(huì)被實(shí)現(xiàn);而如果函數(shù)中拋出一個(gè)錯(cuò)誤,那么 Promise 就會(huì)被拒絕。
await 關(guān)鍵字可以被用來(lái)等待一個(gè) Promise 被解決并返回其實(shí)現(xiàn)的值。如果傳給 await 的值不是一個(gè) Promise,那它會(huì)把這個(gè)值轉(zhuǎn)化為一個(gè)已解決的 Promise。
const rp = require('request-promise') async function main () { const result = await rp('https://google.com') const twenty = await 20 // 睡個(gè)1秒鐘 await new Promise (resolve => { setTimeout(resolve, 1000) }) return result } main() .then(console.log) .catch(console.error)
2 向 async 函數(shù)遷移
如果你的 Node.js 應(yīng)用已經(jīng)在使用Promise,那你只需要把原先的鏈?zhǔn)秸{(diào)用改寫(xiě)為對(duì)你的這些 Promise 進(jìn)行 await。
如果你的應(yīng)用還在使用回調(diào)函數(shù),那你應(yīng)該以漸進(jìn)的方式轉(zhuǎn)向使用 async 函數(shù)。你可以在開(kāi)發(fā)一些新功能的時(shí)候使用這項(xiàng)新技術(shù)。當(dāng)你必須調(diào)用一些舊有的代碼時(shí),你可以簡(jiǎn)單地把它們包裹成為 Promise 再用新的方式調(diào)用。
要做到這一點(diǎn),你可以使用內(nèi)建的 util.promisify方法:
const util = require('util') const {readFile} = require('fs') const readFileAsync = util.promisify(readFile) async function main () { const result = await readFileAsync('.gitignore') return result } main() .then(console.log) .catch(console.error)
3 Async 函數(shù)的最佳實(shí)踐
3.1 在 express 中使用 async 函數(shù)
express 本來(lái)就支持 Promise,所以在 express 中使用 async 函數(shù)是比較簡(jiǎn)單的:
const express = require('express') const app = express() app.get('/', async (request, response) => { // 在這里等待 Promise // 如果你只是在等待一個(gè)單獨(dú)的 Promise,你其實(shí)可以直接將將它作為返回值返回,不需要使用 await 去等待。 const result = await getContent() response.send(result) }) app.listen(process.env.PORT)
但正如 Keith Smith 所指出的,上面這個(gè)例子有一個(gè)嚴(yán)重的問(wèn)題——如果 Promise 最終被拒絕,由于這里沒(méi)有進(jìn)行錯(cuò)誤處理,那這個(gè) express 路由處理器就會(huì)被掛起。
為了修正這個(gè)問(wèn)題,你應(yīng)該把你的異步處理器包裹在一個(gè)對(duì)錯(cuò)誤進(jìn)行處理的函數(shù)中:
const awaitHandlerFactory = (middleware) => { return async (req, res, next) => { try { await middleware(req, res, next) } catch (err) { next(err) } } } // 然后這樣使用: app.get('/', awaitHandlerFactory(async (request, response) => { const result = await getContent() response.send(result) }))
3.2 并行執(zhí)行
比如說(shuō)你正在編寫(xiě)這樣一個(gè)程序,一個(gè)操作需要兩個(gè)輸入,其中一個(gè)來(lái)自于數(shù)據(jù)庫(kù),另一個(gè)則來(lái)自于一個(gè)外部服務(wù):
async function main () { const user = await Users.fetch(userId) const product = await Products.fetch(productId) await makePurchase(user, product) }
在這個(gè)例子中,會(huì)發(fā)生什么呢?
你的代碼會(huì)首先去獲取 user,
然后獲取 product,
最后再進(jìn)行支付。
如你所見(jiàn),由于前兩步之間并沒(méi)有相互依賴關(guān)系,其實(shí)你完全可以將它們并行執(zhí)行。這里,你應(yīng)該使用 Promise.all 方法:
async function main () { const [user, product] = await Promise.all([ Users.fetch(userId), Products.fetch(productId) ]) await makePurchase(user, product) }
而有時(shí)候,你只需要其中最快被解決的 Promise 的返回值——這時(shí),你可以使用 Promise.race 方法。
3.3 錯(cuò)誤處理
考慮下面這個(gè)例子:
async function main () { await new Promise((resolve, reject) => { reject(new Error('error')) }) } main() .then(console.log)
當(dāng)執(zhí)行這段代碼的時(shí)候,你會(huì)看到類似這樣的信息:
(node:69738) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: error
(node:69738) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
在較新的 Node.js 版本中,如果 Promise 被拒絕且未得到處理,整個(gè) Node.js 進(jìn)程就會(huì)被中斷。因此必要的時(shí)候你應(yīng)該使用 try-catch:
const util = require('util') async function main () { try { await new Promise((resolve, reject) => { reject(new Error('---')) }) } catch (err) { // 在這里處理錯(cuò)誤 // 根據(jù)你的需要,有時(shí)候把錯(cuò)誤直接再拋出也是可行的 } } main() .then(console.log) .catch(console.error)
可是,使用 try-catch 可能會(huì)隱藏掉一些重要的異常,比如像系統(tǒng)錯(cuò)誤,你可能更想把它再拋出來(lái)。關(guān)于在什么情況下你應(yīng)該將錯(cuò)誤再次拋出,我強(qiáng)烈建議你去讀一下 Eran 的這篇文章。
3.4 更為復(fù)雜的流程控制
Caolan McMahon 的 async 是一個(gè)出現(xiàn)較早的用于 Node.js 中異步流程控制的庫(kù)。它提供了一些進(jìn)行異步操作控制的幫助工具,比如:
mapLimit, filterLimit, concatLimit,
以及 priorityQueue。
如果你不打算重新發(fā)明輪子,不想把同樣的邏輯自己再實(shí)現(xiàn)一遍,并且愿意信賴這個(gè)經(jīng)過(guò)實(shí)踐檢驗(yàn)的、每月下載量高達(dá) 5000 萬(wàn)的庫(kù),你可以結(jié)合 util.promisify 簡(jiǎn)單地重用這些函數(shù):
const util = require('util') const async = require('async') const numbers = [ 1, 2, 3, 4, 5 ] mapLimitAsync = util.promisify(async.mapLimit) async function main () { return await mapLimitAsync(numbers, 2, (number, done) => { setTimeout(function () { done(null, number * 2) }, 100) }) } main() .then(console.log) .catch(console.error)
上述內(nèi)容就是 async 函數(shù)如何在Node.js中使用,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
標(biāo)題名稱:async函數(shù)如何在Node.js中使用
本文路徑:http://jinyejixie.com/article12/iehsdc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營(yíng)銷(xiāo)、Google、品牌網(wǎng)站建設(shè)、企業(yè)網(wǎng)站制作、網(wǎng)站設(shè)計(jì)公司、靜態(tài)網(wǎng)站
聲明:本網(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í)需注明來(lái)源: 創(chuàng)新互聯(lián)