欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

在 Node.js 中使用 async 函數(shù)的方法

 更新時間:2017年11月17日 11:08:21   作者:柳佳  
利用 async 函數(shù),你可以把基于 Promise 的異步代碼寫得就像同步代碼一樣。一旦你使用 async 關(guān)鍵字來定義了一個函數(shù),那你就可以在這個函數(shù)內(nèi)使用 await 關(guān)鍵字。下面通過本文給大家分享Node.js 中使用 async 函數(shù)的方法,一起看看吧

借助于新版 V8 引擎,Node.js 從 7.6 開始支持 async 函數(shù)特性。今年 10 月 31 日,Node.js 8 也開始成為新的長期支持版本,因此你完全可以放心大膽地在你的代碼中使用 async 函數(shù)了。在這邊文章里,我會簡要地介紹一下什么是 async 函數(shù),以及它會如何改變我們編寫 Node.js 應(yīng)用的方式。

1 什么是 async 函數(shù)

利用 async 函數(shù),你可以把基于 Promise 的異步代碼寫得就像同步代碼一樣。一旦你使用 async 關(guān)鍵字來定義了一個函數(shù),那你就可以在這個函數(shù)內(nèi)使用 await 關(guān)鍵字。當(dāng)一個 async 函數(shù)被調(diào)用時,它會返回一個 Promise。當(dāng)這個 async 函數(shù)返回一個值時,那個 Promise 就會被實(shí)現(xiàn);而如果函數(shù)中拋出一個錯誤,那么 Promise 就會被拒絕。

await 關(guān)鍵字可以被用來等待一個 Promise 被解決并返回其實(shí)現(xiàn)的值。如果傳給 await 的值不是一個 Promise,那它會把這個值轉(zhuǎn)化為一個已解決的 Promise。

const rp = require('request-promise')
async function main () {
 const result = await rp('https://google.com')
 const twenty = await 20
 // 睡個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)用改寫為對你的這些 Promise 進(jìn)行 await。

如果你的應(yīng)用還在使用回調(diào)函數(shù),那你應(yīng)該以漸進(jìn)的方式轉(zhuǎn)向使用 async 函數(shù)。你可以在開發(fā)一些新功能的時候使用這項新技術(shù)。當(dāng)你必須調(diào)用一些舊有的代碼時,你可以簡單地把它們包裹成為 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 本來就支持 Promise,所以在 express 中使用 async 函數(shù)是比較簡單的:

const express = require('express')
const app = express()
app.get('/', async (request, response) => {
 // 在這里等待 Promise
 // 如果你只是在等待一個單獨(dú)的 Promise,你其實(shí)可以直接將將它作為返回值返回,不需要使用 await 去等待。
 const result = await getContent()
 response.send(result)
})
app.listen(process.env.PORT)

但正如 Keith Smith 所指出的,上面這個例子有一個嚴(yán)重的問題——如果 Promise 最終被拒絕,由于這里沒有進(jìn)行錯誤處理,那這個 express 路由處理器就會被掛起。

為了修正這個問題,你應(yīng)該把你的異步處理器包裹在一個對錯誤進(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í)行

比如說你正在編寫這樣一個程序,一個操作需要兩個輸入,其中一個來自于數(shù)據(jù)庫,另一個則來自于一個外部服務(wù):

async function main () {
 const user = await Users.fetch(userId)
 const product = await Products.fetch(productId)
 await makePurchase(user, product)
}

在這個例子中,會發(fā)生什么呢?

你的代碼會首先去獲取 user,

然后獲取 product,

最后再進(jìn)行支付。

如你所見,由于前兩步之間并沒有相互依賴關(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)
}

而有時候,你只需要其中最快被解決的 Promise 的返回值——這時,你可以使用 Promise.race 方法。

3.3 錯誤處理

考慮下面這個例子:

async function main () {
 await new Promise((resolve, reject) => {
  reject(new Error('error'))
 })
}
main()
 .then(console.log)

當(dāng)執(zhí)行這段代碼的時候,你會看到類似這樣的信息:

(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 被拒絕且未得到處理,整個 Node.js 進(jìn)程就會被中斷。因此必要的時候你應(yīng)該使用 try-catch:

const util = require('util')
async function main () {
 try {
  await new Promise((resolve, reject) => {
   reject(new Error('💥'))
  })
 } catch (err) {
  // 在這里處理錯誤
  // 根據(jù)你的需要,有時候把錯誤直接再拋出也是可行的
 }
}
main()
 .then(console.log)
 .catch(console.error)

可是,使用 try-catch 可能會隱藏掉一些重要的異常,比如像系統(tǒng)錯誤,你可能更想把它再拋出來。關(guān)于在什么情況下你應(yīng)該將錯誤再次拋出,我強(qiáng)烈建議你去讀一下 Eran 的這篇文章。

3.4 更為復(fù)雜的流程控制

Caolan McMahon 的 async 是一個出現(xiàn)較早的用于 Node.js 中異步流程控制的庫。它提供了一些進(jìn)行異步操作控制的幫助工具,比如:

mapLimit,
filterLimit,
concatLimit,

以及 priorityQueue。

如果你不打算重新發(fā)明輪子,不想把同樣的邏輯自己再實(shí)現(xiàn)一遍,并且愿意信賴這個經(jīng)過實(shí)踐檢驗(yàn)的、每月下載量高達(dá) 5000 萬的庫,你可以結(jié)合 util.promisify 簡單地重用這些函數(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)

總結(jié)

以上所述是小編給大家介紹的在 Node.js 中使用 async 函數(shù)的方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • 利用Node.js制作爬取大眾點(diǎn)評的爬蟲

    利用Node.js制作爬取大眾點(diǎn)評的爬蟲

    相信每位用過大眾點(diǎn)評的人都知道,大眾點(diǎn)評上有很多美食餐館的信息,所以這篇文章給大家分享利用Node.js實(shí)現(xiàn)爬取大眾點(diǎn)評的爬蟲,正好可以拿來練練手Node.js。感興趣的可以參考借鑒。
    2016-09-09
  • Node.js中DNS模塊學(xué)習(xí)總結(jié)

    Node.js中DNS模塊學(xué)習(xí)總結(jié)

    本篇文章給大家詳細(xì)介紹了Node.js中DNS模塊的相關(guān)知識點(diǎn),以及相關(guān)的實(shí)例代碼做了分享,有興趣的朋友參考下。
    2018-02-02
  • nodejs個人博客開發(fā)第六步 數(shù)據(jù)分頁

    nodejs個人博客開發(fā)第六步 數(shù)據(jù)分頁

    這篇文章主要為大家詳細(xì)介紹了nodejs個人博客開發(fā)的數(shù)據(jù)分頁,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • 學(xué)習(xí)node.js 斷言的使用詳解

    學(xué)習(xí)node.js 斷言的使用詳解

    這篇文章主要介紹了學(xué)習(xí)node.js 斷言的使用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • koa-router源碼學(xué)習(xí)小結(jié)

    koa-router源碼學(xué)習(xí)小結(jié)

    這篇文章主要介紹了koa-router源碼學(xué)習(xí)小結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • node 版本切換的實(shí)現(xiàn)

    node 版本切換的實(shí)現(xiàn)

    這篇文章主要介紹了node 版本切換的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • 使用Node.js為其他程序編寫擴(kuò)展的基本方法

    使用Node.js為其他程序編寫擴(kuò)展的基本方法

    這篇文章主要介紹了使用Node.js為其他程序編寫擴(kuò)展的基本方法 ,文中示例是通過Node讓JavaScript代碼與C++應(yīng)用產(chǎn)生交互,需要的朋友可以參考下
    2015-06-06
  • 深入理解nodejs中Express的中間件

    深入理解nodejs中Express的中間件

    一個Express應(yīng)用就是在調(diào)用各種中間件??梢娭虚g件在web應(yīng)用開發(fā)中的重要性,有興趣的可以了解一下
    2017-05-05
  • node+express+ejs使用模版引擎做的一個示例demo

    node+express+ejs使用模版引擎做的一個示例demo

    本篇文章主要介紹了node+express+ejs使用模版引擎做的一個示例demo,具有一定參考價值,有興趣的小伙伴可以了解一下
    2017-09-09
  • node.js中的fs.lstat方法使用說明

    node.js中的fs.lstat方法使用說明

    這篇文章主要介紹了node.js中的fs.lstat方法使用說明,本文介紹了fs.lstat的方法說明、語法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12

最新評論