在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,res,next)
  }catch(next)
 }
}
module.exports = asyncHandler;

接下来,在异步函数中引入中间件处理:

app.use(asyncHandler(async(req, res, 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, res, 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
风云阁资源网 Design By www.bgabc.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
风云阁资源网 Design By www.bgabc.com

P70系列延期,华为新旗舰将在下月发布

3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。

而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?

根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。