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的面向对象方法以及差别
Mar 31 Javascript
前台js改变Session的值(用ajax实现)
Dec 28 Javascript
jquery插件unobtrusive实现片段式加载
Jun 15 Javascript
AngularJS中的JSONP实例解析
Dec 01 Javascript
js 实现省市区三级联动菜单效果
Feb 20 Javascript
详解基于Angular4+ server render(服务端渲染)开发教程
Aug 28 Javascript
jQuery niceScroll滚动条错位问题的解决方法
Feb 03 jQuery
vue-router懒加载速度缓慢问题及解决方法
Nov 25 Javascript
JavaScript中filter的用法实例分析
Feb 27 Javascript
js实现类似iphone的网页滑屏解锁功能示例【附源码下载】
Jun 10 Javascript
详解vue中v-bind:style效果的自定义指令
Jan 21 Javascript
Vue如何实现监听组件原生事件
Jul 03 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模板,主要想体现一下思路
2006/12/25 PHP
PHP 网页过期时间的控制代码
2009/06/29 PHP
php使用qr生成二维码的示例分享
2014/01/20 PHP
php实现的简单中文验证码功能示例
2017/01/03 PHP
php封装json通信接口详解及实例
2017/03/07 PHP
thinkPHP分页功能实例详解
2017/05/05 PHP
Thinkphp5 微信公众号token验证不成功的原因及解决方法
2017/11/12 PHP
JQUERY设置IFRAME的SRC值的代码
2010/11/30 Javascript
js中eval()函数和trim()去掉字符串左右空格应用
2013/02/02 Javascript
JS日期和时间选择控件升级版(自写)
2013/08/02 Javascript
关于jquery中全局函数each使用介绍
2013/12/10 Javascript
jQuery实现隔行背景色变色
2014/11/24 Javascript
js计算任意值之间随机数的方法
2015/01/16 Javascript
AngularJS控制器继承自另一控制器
2016/05/09 Javascript
Javascript动画效果(3)
2016/10/11 Javascript
Vuex 单状态库与多模块状态库详解
2018/12/11 Javascript
nodejs搭建本地服务器并访问文件操作示例
2019/05/11 NodeJs
JS使用new操作符创建对象的方法分析
2019/05/30 Javascript
Javascript 对象(object)合并操作实例分析
2019/07/30 Javascript
jQuery--遍历操作实例小结【后代、同胞及过滤】
2020/05/22 jQuery
[02:35]DOTA2英雄基础教程 狙击手
2014/01/14 DOTA
[01:14:34]DOTA2上海特级锦标赛C组资格赛#2 LGD VS Newbee第一局
2016/02/28 DOTA
[06:15]2016国际邀请赛中国区预选赛单车采访:我顶WINGS
2016/06/27 DOTA
[46:37]LGD vs TNC 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
Python排序搜索基本算法之堆排序实例详解
2017/12/08 Python
django模板加载静态文件的方法步骤
2019/03/01 Python
Python使用sax模块解析XML文件示例
2019/04/04 Python
Python facenet进行人脸识别测试过程解析
2019/08/16 Python
Python学习笔记之函数的参数和返回值的使用
2019/11/20 Python
AmazeUI折叠式卡片布局,整合内容列表、表格组件实现
2020/08/20 HTML / CSS
应届大学生的推荐信
2013/11/20 职场文书
小学语文国培感言
2014/03/04 职场文书
汽车机修工岗位职责
2014/03/06 职场文书
化学专业大学生职业生涯规划范文
2014/09/13 职场文书
就业推荐表自我评价范文
2015/03/02 职场文书
2015年副班长工作总结
2015/05/15 职场文书