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 相关文章推荐
js函数名与form表单元素同名冲突的问题
Mar 07 Javascript
浅析Node.js中使用依赖注入的相关问题及解决方法
Jun 24 Javascript
jquery实现仿新浪微博评论滚动效果
Aug 06 Javascript
基于jquery实现的树形菜单效果代码
Sep 06 Javascript
jquery利用拖拽方式在图片上添加热链接
Nov 24 Javascript
原生JavaScript实现Ajax的方法
Apr 07 Javascript
如何使用bootstrap框架 bootstrap入门必看!
Apr 13 Javascript
使用bootstraptable插件实现表格记录的查询、分页、排序操作
Aug 06 Javascript
手淘flexible.js框架使用和源代码讲解小结
Oct 15 Javascript
解决ele ui 表格表头太长问题的实现
Nov 13 Javascript
用js编写留言板
Mar 17 Javascript
jquery实现上传文件进度条
Mar 26 jQuery
详解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
yii实现图片上传及缩略图生成的方法
2014/12/04 PHP
php array_keys 返回数组的键名
2016/10/25 PHP
Zend Framework分发器用法示例
2016/12/11 PHP
关于Curl在Swoole协程中的解决方案详析
2019/09/12 PHP
input、button的不同type值在ajax提交表单时导致的陷阱
2009/02/24 Javascript
10分钟学会写Jquery插件实例教程
2014/09/06 Javascript
JavaScript不使用prototype和new实现继承机制
2014/12/29 Javascript
js完美解决IE6不支持position:fixed的bug
2015/04/24 Javascript
jquery实现滑动特效代码
2015/08/10 Javascript
js中class的点击事件没有效果的解决方法
2016/10/13 Javascript
jQuery插件HighCharts绘制2D金字塔图效果示例【附demo源码下载】
2017/03/09 Javascript
jQuery EasyUI开发技巧总结
2017/09/26 jQuery
微信小程序自定义组件封装及父子间组件传值的方法
2018/08/28 Javascript
JS实现导航栏楼层特效
2020/01/01 Javascript
React中获取数据的3种方法及优缺点
2020/02/18 Javascript
JS 5种遍历对象的方式
2020/06/16 Javascript
uni-app使用countdown插件实现倒计时
2020/11/01 Javascript
Map与WeakMap类型在JavaScript中的使用详解
2020/11/18 Javascript
[01:00]一分钟回顾2018DOTA2亚洲邀请赛现场活动
2018/04/07 DOTA
Android 兼容性问题:java.lang.UnsupportedOperationException解决办法
2017/03/19 Python
python处理multipart/form-data的请求方法
2018/12/26 Python
详解Numpy数组转置的三种方法T、transpose、swapaxes
2019/05/27 Python
Python命名空间namespace及作用域原理解析
2020/06/05 Python
Pytorch实现将模型的所有参数的梯度清0
2020/06/24 Python
html5+css3气泡组件的实现
2014/11/21 HTML / CSS
html2canvas把div保存图片高清图的方法示例
2018/03/05 HTML / CSS
Mavi牛仔裤美国官网:土耳其著名牛仔品牌
2016/09/24 全球购物
美国轮胎网站:Priority Tire
2018/11/28 全球购物
俄罗斯领先的移动和数字设备在线商店:Svyaznoy.ru
2020/12/21 全球购物
幼师自荐信范文
2013/10/06 职场文书
六查六看六改心得体会
2014/10/14 职场文书
投诉信格式范文
2015/07/02 职场文书
php 获取音视频时长,PHP 利用getid3 获取音频文件时长等数据
2021/04/01 PHP
python如何利用traceback获取详细的异常信息
2021/06/05 Python
Java实现多文件上传功能
2021/06/30 Java/Android
golang用type-switch判断interface的实际存储类型
2022/04/14 Golang