这是Angular+Sequelize系列的第四篇文章, 应该是搭建后台部分的最后一篇, 通过前面3篇文章, 从0到1, 我们可以成功建立以Express+Sequelize为框架的REST API, 使用VS Code进行调用REST和debug Node代码, 并且对于数据库CRUD都不在话下. 今天接着讨论最后两点, 分别是错误处理(Error Handling)和跨域名访问设定(Cross-Origins Access).
1: 错误处理(Error Handling)
上篇文章中, 创建了关于User REST, 如下图, 在create方法中只做了简单的判空, 但并没有进行任何的错误处理(即try-catch).
这样会造成什么结果呢? 如果数据库表做了改动 (比如: 某column由nullable变not null, 或添加了个外键或constraint, 亦或是任何短暂连接问题), 那么发生的错误就会直接被抛至到最外层. 但我们希望的处理情况当然不是这样, 如果一些可以pre-check的条件(例如判空), 则尽量预先判断; 但对于一些无法预判的错误, 则需要进行异常捕获, 并且抛出处理后的异常, 例如HTTP 500 Internal Server Error.
可能有同学会说, 这还不简单, 把数据库操作的那部分代码 套上try-catch, 然后在catch的代码块中加上抛出HTTP 500的error. 如下图这样:
看上去很完美, 但仔细想想, 细思极恐的事情就来了; 每个DB CRUD的方法都要加? 现在只有User一个REST, 要是来几十上百个REST, 那不疯了... (成功造码三千行, 年底评优上青云. [得意])
有没有办法, 可以只在一块地方写一个通用的错误处理块, 然后适用于所有REST代码抛出的错误呢? Express框架是有这部分设计的, 真是造福全码农啊. 具体做法是在index.js中加上app.use()来设定一个通用的错误处理代码块, 如下图:
红色粗字醒目提示: app.use()定义的错误处理, 必须放在代码最后!!!
迫不及待, 感觉去浏览器或者REST Client插件试试看效果, 堪称完美:
接下来就可以把controller里所有DB方法的try catch统统去掉, 一般错误的处理就放心的交由这块代码来做统一处理. 等等等, 事出太完美, 挖坑脚跟前. 怎么controller抛出的错误就没被处理呢?? 我去什么操作? (大家可以尝试一下, 在controller里随便throw个error, 是不会被app.use那块代码处理的) 一顿网上搜索, why why why?
hm... 还记得我们的controller是怎么写的么? 每个方法都有async修饰, 每个db操作的地方则有await修饰. 异步的方法抛出的错误是无法被app.use统一catch住, 更不用说统一处理了.
虾米? 白折腾了? 别急别急, 且听我慢慢填坑. 对于异步方法的错误处理, 想要捕获错误, 就需要将异步方法包一层面粉壳, 这样错误飞出来了, 面粉就会喷射, Express就能捕获啦. (自行脑补情景 [奋斗])
先安装Express面粉壳:
npm install -save express-async-handler
接着在route.config.js中给每个REST方法套上面粉壳, 如下图:
接着, 你将controller的任何一个方法, 改成直接抛错error或httpError测试, 你会发现无论是同步还是异步的方法, 错误都会被app.use定义的错误处理代码块统一处理. 完美! [呲牙]
2: 跨域名访问设定 (Cross-Origins Access)
说到第二点, 其实是我在做Angular前端时碰到的坑, 默认开发环境, Angular地址是http://localhost:4200, Express后台REST是http://localhost:3000, 在浏览器和RestClient里访问得好好的REST, 到Angular里咋就不成了呢? 并且抛出了个Cross-Origins的错误.
这里不得不先提一下跨域名访问限制: 由于安全考虑, 浏览器规定JavaScript不能操作其他域名下的DOM, 也不得请求/接受其他域名下的xhr请求. 只要协议(http/https), 域名, 端口号有一者不同, 则被视为跨域.
但跨域名调用REST实在太普遍啦, 如果不能跨域名访问REST, 甚至会反问: REST要来有啥用? 通常以往要解决跨域调用是挺麻烦的 (大家可以自行搜索, 网上五花八门, 答案都不简单), 幸好Express搭建的REST也考虑到这个问题, 我们可以使用CORS (Cross-Origins Resource Sharing)来达到跨域名访问的目的.
好了, 概念部分就瞎扯到这里, 需要更完整来龙去脉的同学可以自行搜索, 反正我又差点搜得两眼发涩, 气神错乱. 来来来, 直接看怎么做最重要.
先安装cors lib:
npm install -save cors
然后在index.js中增加这么一小段代码, 如图:
短小精悍, 永久解决了跨域名访问的问题. 当然有需要的同学可以查阅cors的官方文档, cors其实支持各种customized功能, 我这里只是简单粗暴地把所有的REST API都设定为支持跨域名访问.
好啦今天的文章就到这里了, 经过4集连续剧, 我们从0到1搭建了Express Rest, 配置了Sequelize数据库连接, 尝试了VS Code调试代码和RestClient调用API, 以及一些不起眼又很烦人的坑坑洼洼. 4集内容, 麻雀虽小五脏俱全, 希望能帮到刚刚入门Node JS的同学.
都看到这里了, 点个赞再走呗, 感谢!
本文暂时没有评论,来添加一个吧(●'◡'●)