中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

NodeJS處理Express中異步錯誤的示例分析

發布時間:2021-07-12 14:49:04 來源:億速云 閱讀:370 作者:小新 欄目:web開發

小編給大家分享一下NodeJS處理Express中異步錯誤的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

Express 內置的異步錯誤處理

在默認情況下,Express 會捕獲所有在路由處理函數中的拋出的異常,然后將它傳給下一個錯誤處理中間件:

app.get('/', function (req, res) {
 throw new Error('oh no!')
})
app.use(function (err, req, res, next) {
 console.log(err.message) // 噢!不!
})

對于同步執行的代碼,以上的處理已經足夠簡單。然而,當異步程序在執行時拋出異常的情況,Express 就無能為力。原因在于當你的程序開始執行回調函數時,它原來的棧信息已經丟失。

app.get('/', function (req, res) {
 queryDb(function (er, data) {
  if (er) throw er
 })
})
app.use(function (err, req, res, next) {
 // 這里拿不到錯誤信息
})

對于這種情況,可以使用 next 函數來將錯誤傳遞給下一個錯誤處理中間件

app.get('/', function (req, res, next) {
 queryDb(function (err, data) {
  if (err) return next(err)
  // 處理數據

  makeCsv(data, function (err, csv) {
   if (err) return next(err)
   // 處理 csv

  })
 })
})
app.use(function (err, req, res, next) {
 // 處理錯誤
})

使用這種方法雖然一時爽,卻帶來了兩個問題:

你需要顯式地在錯誤處理中間件中分別處理不同的異常。

一些隱式異常并沒有被處理(如嘗試獲取一個對象并不存在的屬性)

利用 Promise 傳遞異步錯誤

在異步執行的程序中使用 Promise 處理任何顯式或隱式的異常情況,只需要在 Promise 鏈尾加上 .catch(next) 即可。

app.get('/', function (req, res, next) {
 // do some sync stuff
 queryDb()
  .then(function (data) {
   // 處理數據
   return makeCsv(data)
  })
  .then(function (csv) {
   // 處理 csv
  })
  .catch(next)
})
app.use(function (err, req, res, next) {
 // 處理錯誤
})

現在,所有異步和同步程序都將被傳遞到錯誤處理中間件。棒棒的。

雖然 Promise 讓異步錯誤的傳遞變得容易,但這樣的代碼仍然有一些冗長和刻板。這時候 promise generator 就派上了用場。

用 Generators 簡化代碼

如果你使用的環境原生支持 Generators,你可以手動實現以下的功能。不過這里我們將借用 Bluebird.coroutine 來說明如何使用 Promise generator 來簡化剛才的代碼。

盡管接下來的例子使用的是 bluebird ,其它 Promise 庫(如 co)也都支持 Promise generator.

首先,我們需要使得 Express 路由函數與 Promise generator 兼容:

var Promise = require('bluebird')
function wrap (genFn) { // 1
  var cr = Promise.coroutine(genFn) // 2
  return function (req, res, next) { // 3
    cr(req, res, next).catch(next) // 4
  }
}

這個函數是一個高階函數,它做了以下幾件事情:(分別與代碼片段中的注釋對應)

以 Genrator 為唯一的輸入

讓這個函數懂得如何 yield promise

返回一個普通的 Express 路由函數

當這個函數被執行時,它會使用 coroutine 來 yield promise,捕獲期間發生的異常,然后將其傳遞給 next 函數

借助這個函數,我們就可以這樣構造路由函數:

app.get('/', wrap(function *(req, res) {
 var data = yield queryDb()
 // 處理數據
 var csv = yield makeCsv(data)
 // 處理 csv
}))
app.use(function (err, req, res, next) {
 // 處理錯誤
})

現在,Express 的異步錯誤處理流程的可讀性已經近乎令人滿意,而且你可以像寫同步執行的代碼一樣去書寫異步執行的代碼,唯一不要忘了的就是 yield promises。

然而這還不是終點,ES7 的 async/await 提議可以讓代碼變得更簡潔。

使用 ES7 async/await

ES7 async/await 的行為就像 Promise Generator 一樣,只不過它可以被用到更多的地方(如類方法或者胖箭頭函數)。

為了在 Express 中使用 async/await,同時優雅地處理異步錯誤,我們仍然需要一個與上文提到的 wrap 類似的函數:

let wrap = fn => (...args) => fn(...args).catch(args[2])
這樣,我們就可以按底下這種方式書寫路由函數:

app.get('/', wrap(async function (req, res) {
 let data = await queryDb()
 // 處理數據
 let csv = await makeCsv(data)
 // 處理 csv
}))

現在可以愉快地寫代碼了

有了對同步和異步錯誤的處理,你可以用新的方式來開發 Express App。但有兩點需要注意:

要習慣使用 throw ,它使得你的代碼目的明確,throw 會明確地將程序引到錯誤處理中間件,這對同步或異步的程序都是適用的。
遇到特殊情況,當你覺得有必要時,也可以自行 try/catch。

app.get('/', wrap(async (req, res) => {
   if (!req.params.id) {
    throw new BadRequestError('Missing Id')
   }
   let companyLogo
   try {
    companyLogo = await getBase64Logo(req.params.id)
   } catch (err) {
    console.error(err)
    companyLogo = genericBase64Logo
   }
  }))

要習慣使用 custom error classes ,如 BadRequestError,因為這可以讓你在錯誤處理中間件中更方便地分類處理。

app.use(function (err, req, res, next) {
   if (err instanceof BadRequestError) {
    res.status(400)
    return res.send(err.message)
   }
   ...
  })

以上是“NodeJS處理Express中異步錯誤的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

贵德县| 图们市| 勃利县| 泗水县| 清丰县| 新密市| 共和县| 沂源县| 平利县| 通河县| 增城市| 霍城县| 东海县| 孝感市| 会泽县| 恭城| 依兰县| 大田县| 郯城县| 内江市| 富源县| 会宁县| 宣化县| 乌兰察布市| 桦甸市| 沁源县| 贵州省| 信阳市| 宜兰市| 蕲春县| 民和| 织金县| 嘉善县| 伊春市| 灵宝市| 新竹县| 武川县| 县级市| 西丰县| 荥经县| 庆城县|