1. 程式人生 > 程式設計 >express非同步函式異常捕獲示例詳解

express非同步函式異常捕獲示例詳解

在express中時使用 Async/await 編寫非同步程式碼時,每個 async 函式都要包裹在try/catch中,程式碼量多了看著冗餘不優雅,express又不像koa的非同步機制可以訂閱全域性的error事件,為了解決這個問題,需要寫個捕獲非同步函式異常的中介軟體。

uncaughtException

開始能想到的肯定是try/catch了,但是也想過能否使用nodejs提供的uncaughtException事件,在全域性捕獲異常,例如下面的程式碼:

process.on("uncaughtException",(err) => console.log("uncaught Exception"));

const asyncError=()=>{
 throw new Error("some Error");
}

asyncError();

asyncError方法裡面丟擲的異常會被 uncaughtException訂閱,但是在非同步函式中,並沒走到 uncaughtException,還是會丟擲異常:

process.on("uncaughtException",(err) => console.log("uncaught Exception"));

const asyncError=()=>{
 throw new Error("some Error");
}

(async ()=>{
 // 丟擲異常
 asyncError();
})()

而且Promise.reject也沒走到uncaughtException裡面:

const asyncError=()=>{
 return Promise.reject("some error")
}

(async ()=>{
 // 丟擲異常
 await asyncError();
})()

所以在express中使用nodejs提供的uncaughtException處理非同步錯誤不太合適,一方面沒法捕獲和定位上下文錯誤,另一方面也沒法將錯誤異常提供給中介軟體函式處理

解決思路

要處理express中的非同步函式錯誤,最好的方法當然是編寫處理異常的中介軟體了,try/catch開路,包裹中介軟體方法,catch到的異常直接交給next函式處理,程式碼如下:

 const asyncHandler = fn =>{
 return (req,res,next)=>{
  try{
   fn(req,next)
  }catch(next)
 }
}
module.exports = asyncHandler;

接下來,在非同步函式中引入中介軟體處理:

app.use(asyncHandler(async(req,next) => {
 await authenticate(req);
 next();
}));

app.get('/async',asyncHandler(async(req,res) => {
 const result = await request('http://example.com');
 res.end(result);
}));

使用asyncHandler方法包裹的async/await函式,如果出現錯誤就會被Error-handling中介軟體捕獲了

但是每次用到非同步函式的時候都要包裹asyncHandler方法,真正用起來也不是很爽,這裡推薦使用express-async-errors中介軟體,其原理是將express裡面的中間全部包裹上一層asyncHandler方法,讓錯誤異常無所遁形,全部跑到Error-handling中介軟體。

前提是引入express後,先引入express-async-errors方法:

const express = require('express');
require('express-async-errors');
const User = require('./models/user');
const app = express();

app.get('/users',async (req,res) => {
 const users = await User.findAll();
 res.send(users);
});

接下來的在非同步函式中,就不用都包裹上try/catch了,有錯誤提前throw Error,寫起程式碼來美滋滋:

app.use(async (req,res) => {
 const user = await User.findByToken(req.get('authorization'));

 if (!user) throw Error("access denied");
});

app.use((err,req,next) => {
 if (err.message === 'access denied') {
 res.status(403);
 res.json({ error: err.message });
 }

 next(err);
});~~~~

參考連結:

  • Using Async/await in Express
  • Handling errors in express async middleware

到此這篇關於express非同步函式異常捕獲示例的文章就介紹到這了,更多相關express非同步函式異常捕獲內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!