express异步函数异常捕获示例详解


Posted in Javascript onNovember 30, 2020

在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

到此这篇关于express异步函数异常捕获示例的文章就介绍到这了,更多相关express异步函数异常捕获内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
理解JavaScript中的事件
Sep 23 Javascript
JavaScript中使用正则匹配多条,且获取每条中的分组数据
Nov 30 Javascript
js 延迟加载 改变JS的位置加快网页加载速度
Dec 11 Javascript
Javascript实现单张图片浏览
Dec 18 Javascript
JavaScript中判断变量是数组、函数或是对象类型的方法
Feb 25 Javascript
基于JavaScript实现熔岩灯效果导航菜单
Jan 04 Javascript
JS实现的按钮点击颜色切换功能示例
Oct 19 Javascript
详解node child_process模块学习笔记
Jan 24 Javascript
react-native android状态栏的实现
Jun 15 Javascript
JS实现百度网盘任意文件强制下载功能
Aug 31 Javascript
详解Vue 如何监听Array的变化
Jun 06 Javascript
微信小程序实现聊天室
Aug 21 Javascript
详解Vue 的异常处理机制
Nov 30 #Vue.js
ESLint 是如何检查 .vue 文件的
Nov 30 #Vue.js
JavaScript实现商品评价五星好评
Nov 30 #Javascript
详解React路由传参方法汇总记录
Nov 29 #Javascript
基于jQuery拖拽事件的封装
Nov 29 #jQuery
原生js+canvas实现验证码
Nov 29 #Javascript
原生js实现弹幕效果
Nov 29 #Javascript
You might like
php桌面中心(四) 数据显示
2007/03/11 PHP
PHP Session机制简介及用法
2014/08/19 PHP
Javascript 更新 JavaScript 数组的 uniq 方法
2008/01/23 Javascript
jQuery页面滚动浮动层智能定位实例代码
2011/08/23 Javascript
js实现按钮加背景图片常用方法
2014/11/01 Javascript
js如何改变文章的字体大小
2016/01/08 Javascript
JavaScript仿flash遮罩动画效果
2016/06/15 Javascript
bootstrapValidator 重新启用提交按钮的方法
2017/02/20 Javascript
Angularjs按需查询实例代码
2017/10/30 Javascript
JavaScript中正则表达式使数字、中文或指定字符高亮显示
2017/10/31 Javascript
vue项目中用cdn优化的方法
2018/01/03 Javascript
JS与jQuery判断文本框还剩多少字符可以输入的方法
2018/09/01 jQuery
Python新手实现2048小游戏
2015/03/31 Python
Python 爬虫爬取指定博客的所有文章
2016/02/17 Python
python批量添加zabbix Screens的两个脚本分享
2017/01/16 Python
Python实现的选择排序算法示例
2017/11/29 Python
python中判断文件编码的chardet(实例讲解)
2017/12/21 Python
python引入不同文件夹下的自定义模块方法
2018/10/27 Python
windows7 32、64位下python爬虫框架scrapy环境的搭建方法
2018/11/29 Python
python发送多人邮件没有展示收件人问题的解决方法
2019/06/21 Python
Django 实现图片上传和显示过程详解
2019/07/18 Python
python批量修改xml属性的实现方式
2020/03/05 Python
在jupyter notebook中调用.ipynb文件方式
2020/04/14 Python
Python-openCV开运算实例
2020/07/05 Python
纯css3制作的火影忍者写轮眼开眼至轮回眼及进化过程实例
2014/11/11 HTML / CSS
HTML5手机端弹出遮罩菜单特效代码
2016/01/27 HTML / CSS
MATCHESFASHION.COM美国官网:英国奢侈品零售商
2018/10/29 全球购物
意大利买卖二手奢侈品网站:LAMPOO
2020/06/03 全球购物
如何开启linux的ssh服务
2013/06/03 面试题
户外用品商店创业计划书
2014/01/29 职场文书
打造高效课堂实施方案
2014/03/22 职场文书
2014年幼儿园学期工作总结
2014/12/05 职场文书
2015年度物流工作总结
2015/04/30 职场文书
MySQL COUNT函数的使用与优化
2021/05/10 MySQL
Redisson实现Redis分布式锁的几种方式
2021/08/07 Redis
MySQL修改默认引擎和字符集详情
2021/09/25 MySQL