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 相关文章推荐
ext checkboxgroup 回填数据解决
Aug 21 Javascript
JQuery设置文本框和密码框得到焦点时的样式
Aug 30 Javascript
深入理解jquery中的事件与动画
May 24 Javascript
JavaScript简单实现弹出拖拽窗口(二)
Jun 17 Javascript
jQuery实现点击行选中或取消CheckBox的方法
Aug 01 Javascript
基于jQuery实现弹幕APP
Feb 10 Javascript
Bootstrap table使用方法总结
May 10 Javascript
vue页面使用阿里oss上传功能的实例(一)
Aug 09 Javascript
vue的基本用法与常见指令
Aug 15 Javascript
使用JavaScript获取Django模板指定键值数据
May 27 Javascript
关于vue属性使用和不使用冒号的区别说明
Oct 22 Javascript
pnpm对npm及yarn降维打击详解
Aug 05 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从零开始打造自己的MVC框架之类的自动加载实现方法详解
2019/06/03 PHP
Yii框架分页技术实例分析
2019/08/30 PHP
基于jquery的跨域调用文件
2010/11/19 Javascript
基于jquery的无缝循环新闻列表插件
2011/03/07 Javascript
js substring从右边获取指定长度字符串(示例代码)
2013/12/23 Javascript
jquery实现点击弹出层效果的简单实例
2014/03/03 Javascript
基于jQuery的ajax方法封装
2016/07/14 Javascript
移动端刮刮乐的实现方式(js+HTML5)
2017/03/23 Javascript
JS判断两个对象内容是否相等的方法示例
2017/04/10 Javascript
bootstrap弹出层的多种触发方式
2017/05/10 Javascript
vue2.0+vue-dplayer实现hls播放的示例
2018/03/02 Javascript
快速解决angularJS中用post方法时后台拿不到值的问题
2018/08/14 Javascript
详解Vue项目中出现Loading chunk {n} failed问题的解决方法
2018/09/14 Javascript
详解vue-router导航守卫
2019/01/19 Javascript
百度小程序之间的页面通信过程详解
2019/07/18 Javascript
Net微信网页开发 使用微信JS-SDK获取当前地理位置过程详解
2019/08/26 Javascript
vue调用语音播放的方法
2019/09/27 Javascript
解决Vue 刷新页面导航显示高亮位置不对问题
2019/12/25 Javascript
Vue 中 template 有且只能一个 root的原因解析(源码分析)
2020/04/11 Javascript
[00:34]TI7不朽珍藏III——纯金地穴编织者饰品展示
2017/07/15 DOTA
[01:48]帕吉至宝加入游戏,遗迹战场现“千劫神屠”
2018/04/07 DOTA
python 控制语句
2011/11/03 Python
Python 的内置字符串方法小结
2016/03/15 Python
Python局部变量与全局变量区别原理解析
2020/07/14 Python
Python 的 __str__ 和 __repr__ 方法对比
2020/09/02 Python
HTML5移动开发图片压缩上传功能
2016/11/09 HTML / CSS
英国领先的珍珠首饰品牌:Orchira
2016/09/11 全球购物
2014年大学生四年规划书范文
2014/04/03 职场文书
婚礼秀策划方案
2014/05/19 职场文书
妈妈活动方案
2014/08/15 职场文书
大学生第一学年自我鉴定
2014/09/12 职场文书
员工培训协议书
2014/09/15 职场文书
祖国在我心中演讲稿(小学生)
2014/09/23 职场文书
12.4法制宣传日标语
2014/10/08 职场文书
校长新学期寄语2016
2015/12/04 职场文书
PHP连接MSSQL数据库案例,PHPWAMP多个PHP版本连接SQL Server数据库
2021/04/16 PHP