Koa 中的错误处理解析


Posted in Javascript onApril 09, 2019

不像 express 中在末尾处注册一个声明为 (err, req, res, next) 中间件的方式,koa 刚好相反,在开头进行注册。

app.use(async (ctx, next) => {
 try {
  await next();
 } catch (err) {
  ctx.status = err.status || 500;
  ctx.body = err.message;
  ctx.app.emit("error", err, ctx);
 }
});

这样程序中任何报错都会收敛到此处。此时可以方便地将错误打印到页面,开发时非常便捷。

+   ctx.app.emit('error', err, ctx);

koa 也建议通过 app 来派发错误,然后通过监听 app 上的 error 事件对这些错误做进一步的统一处理和集中管理。

app.on("error", (err, ctx) => {
 /* 错误的集中处理:
  * log 出来
  * 写入日志
  * 写入数据库
  *  ...
  */
});

一个错误捕获并打印到页面的示例:

const Koa = require("koa");
const app = new Koa();

app.use(async (ctx, next) => {
 try {
  await next();
 } catch (err) {
  const status = err.status || 500;
  ctx.status = status;
  ctx.type = "html";
  ctx.body = `
  <b>${status}</b> ${err}
  `;
  // emmit
  ctx.app.emit("error", err, ctx);
 }
});

app.use(ctx => {
 const a = "hello";
 a = "hello world!"; // TypeError: Assignment to constant variable.
 ctx.body = a;
});

app.on("error", (err, ctx) => {
 console.error("Ooops..\n", err);
});

app.listen(3000);

通过 node server.js 启动后访问页面可看到命令行的错误输出。

如果使用 pm2,可通过 —no-daemon 参数使其停留在在命令行以查看输出。

如果不使用上述参数,可通过 pm2 logs [app-name] 来查看。

ctx.throw

朴素的抛错方式需要手动设置状态码及信息对客户端的可见性。

const err = new Error("err msg");
err.status = 401;
err.expose = true;
throw err;

expose 决定是否会返回错误详情给客户端,否则只展示状态对应的错误文案,比如 500 会在浏览器中展示为 Internal Server Error 。

而通过 ctx.throw 这个 helper 方法会更加简洁。

上面的代码片段等价于:

ctx.throw(401, "err msg");

如果不指定状态码,默认为 500。5xx 类错误 expose 默认为 false ,即不会将错误信息返回到 response。

抛错时还可以传递一些额外数据,这些数据会合并到错误对象上,在处理错误的地方可以从 error 上获取。

app.use(ctx => {
 ctx.throw(401, "access_denied", { user: { name: "foo" } });
});

app.on("error", (err, ctx) => {
 console.error("Ooops..\n", err.user);
});

参考

Error Handling
ctx.throw

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
分享几个超级震憾的图片特效
Jan 08 Javascript
你需要知道的10个最佳javascript开发实践小结
Apr 15 Javascript
JS数组排序技巧汇总(冒泡、sort、快速、希尔等排序)
Nov 24 Javascript
JS在onclientclick里如何控制onclick的执行
May 30 Javascript
JS匿名函数类生成方式实例分析
Nov 26 Javascript
Vue组件tree实现树形菜单
Apr 13 Javascript
Javascript创建类和对象详解
May 31 Javascript
JS实现模糊查询带下拉匹配效果
Jun 21 Javascript
mpvue写一个CPASS小程序的示例
Sep 04 Javascript
了解JavaScript函数中的默认参数
May 30 Javascript
layui实现二维码弹窗、并下载到本地的方法
Sep 25 Javascript
vue实现在线预览pdf文件和下载(pdf.js)
Nov 26 Javascript
简单说说如何使用vue-router插件的方法
Apr 08 #Javascript
利用Bootstrap Multiselect实现下拉框多选功能
Apr 08 #Javascript
纯javascript实现选择框的全选与反选功能
Apr 08 #Javascript
详解小程序如何避免多次点击,重复触发事件
Apr 08 #Javascript
「中高级前端面试」JavaScript手写代码无敌秘籍(推荐)
Apr 08 #Javascript
微信小程序BindTap快速连续点击目标页面跳转多次问题处理
Apr 08 #Javascript
vue.js实现会动的简历(包含底部导航功能,编辑功能)
Apr 08 #Javascript
You might like
Php Image Resize图片大小调整的函数代码
2011/01/17 PHP
PHP中ob_start函数的使用说明
2013/11/11 PHP
Yii2搭建后台并实现rbac权限控制完整实例教程
2016/04/28 PHP
php网页版聊天软件实现代码
2016/08/12 PHP
PHP 匿名函数与注意事项详细介绍
2016/11/26 PHP
php mysql实现mysql_select_db选择数据库
2016/12/30 PHP
PHP进程通信基础之信号量与共享内存通信
2017/02/19 PHP
PHP+Ajax实现的无刷新分页功能详解【附demo源码下载】
2017/07/03 PHP
基于PHP实现栈数据结构和括号匹配算法示例
2017/08/10 PHP
Yii2框架实现登陆添加验证码功能示例
2018/07/12 PHP
仅Firefox中链接A无法实现模拟点击以触发其默认行为
2011/07/31 Javascript
javascript 事件处理程序介绍
2012/06/27 Javascript
window.onresize 多次触发的解决方法
2013/11/08 Javascript
jquery的父子兄弟节点查找示例代码
2014/03/03 Javascript
深入探究AngularJS框架中Scope对象的超级教程
2016/01/04 Javascript
node.js连接mongoDB数据库 快速搭建自己的web服务
2016/04/17 Javascript
利用Javascript实现BMI计算器
2016/08/16 Javascript
javascript 中的继承实例详解
2017/05/05 Javascript
python列表操作之extend和append的区别实例分析
2015/07/28 Python
Python3之文件读写操作的实例讲解
2018/01/23 Python
python 读入多行数据的实例
2018/04/19 Python
python 实现二维列表转置
2019/12/02 Python
pytorch torch.nn.AdaptiveAvgPool2d()自适应平均池化函数详解
2020/01/03 Python
Keras实现DenseNet结构操作
2020/07/06 Python
html通过canvas转成base64的方法
2019/07/18 HTML / CSS
使用html2canvas实现将html内容写入到canvas中生成图片
2020/01/03 HTML / CSS
施华洛世奇韩国官网:SWAROVSKI韩国
2018/06/05 全球购物
夏威夷咖啡公司:Hawaii Coffee Company
2019/09/19 全球购物
如何选择使用结构还是类
2014/05/30 面试题
学校招生宣传广告词
2014/03/19 职场文书
小区文明倡议书
2014/05/16 职场文书
入党综合考察材料
2014/06/02 职场文书
横幅标语大全
2014/06/17 职场文书
2014年学校后勤工作总结
2014/12/06 职场文书
趵突泉导游词
2015/02/03 职场文书
nginx部署多前端项目的几种方法
2021/05/25 Servers