Nodejs 回调函数中的坑以及中间件的用法
2016-03-30 21:41
549 查看
在用Nodejs + express 开发后台的过程中,最令人头疼的就是到处存在的回调函数了。不管是http请求,还是数据库请求,都是强制回调的。这是由js本身的特性导致的。
所谓回调,就是指假设A将任务分配给B去运行。之后A就可以把这个任务放在一边,去执行其他任务。当B执行完以后,将结果告诉A,A会捡起之前没完成的任务继续做。有点类似于中断的模式。这样一来,虽然程序的性能得以保证,但是许多问题也是随之而来。
第一个问题是异常捕获变得更加困难。如果在A所执行程序的两端加上try…catch,而在B执行回调过程中发生了错误,A是不会报错的。这点要特别注意。所以要特别注意对返回函数中异常信息的处理。这点是比较令人困扰的。举例如下
典型的回调函数写法
上面这段程序用来在mydql中创建新数据行。当然其他回调的用法也差不多。可以看到,虽然A有try catch对,但是在回调过程中,如果B发生了错误,那么A是不会报错的。只是在回调函数funtion(err, result)中,有相关的错误信息。
第二个问题是回调函数使得代码的执行顺序不再线性,有可能会造成逻辑混乱。还是拿上面的程序举例,稍微修改下
上面这段程序,A在执行第一块代码时,把一个任务交给B去处理。关键是,之后A会按顺序执行下面的代码,第二块代码,第三块代码… 以此类推。那么问题来了,回调函数有可能先于代码块2被执行,也有可能晚于代码块2.那么如果代码块2和回调函数调用了同一个资源,就很有可能会报错。我在写的时候就碰到过一个,使得对一个http请求重复返回了2次内容,但是一个http只能有一个返回呀,于是就报错了。
解决的办法,就是将A后续的代码都放进回调函数中。或者对于两个并行的逻辑,尽量使用if-else逻辑,而不要用if-return逻辑。如下所示
第三个问题,频繁使用回调会使得代码逻辑一片混乱,嵌套过深,可读性和可维护性都非常糟糕。被称作”callback hell”。比如有一个业务逻辑,需要读取一次网页,然后读取若干次数据库。。。于是你的函数就变成这样了。。。
如上所示,不停的嵌套嵌套嵌套。。。。画面太美不敢看。。这时候为了让代码的逻辑更加清晰,需要使用中间件。在express中,是可以使用中间件来处理业务逻辑的。(其他的我不太清楚,应该也是有的)。所谓的中间件有点类似于linux中的管道,前一个函数执行完以后,如果没有返回,就由下一个函数处理。如下所示。(以express应用为例)
每个中间件的参数都是req,res,next. req中有一些请求的必要信息,以及有可能有上一个中间件的执行结果,res表示要返回给客户端的内容,next表示调用下一个中间件,只能在非结尾的中间件中使用
所谓回调,就是指假设A将任务分配给B去运行。之后A就可以把这个任务放在一边,去执行其他任务。当B执行完以后,将结果告诉A,A会捡起之前没完成的任务继续做。有点类似于中断的模式。这样一来,虽然程序的性能得以保证,但是许多问题也是随之而来。
第一个问题是异常捕获变得更加困难。如果在A所执行程序的两端加上try…catch,而在B执行回调过程中发生了错误,A是不会报错的。这点要特别注意。所以要特别注意对返回函数中异常信息的处理。这点是比较令人困扰的。举例如下
典型的回调函数写法
try{ // 程序A req.models.vote.create(record, funtion(err, result){ // 回调函数 if (err) { // blablabla... // 对B执行结果的异常处理 } // A需要完成的接下来的任务 }) }catch(err){ // A的异常处理 }
上面这段程序用来在mydql中创建新数据行。当然其他回调的用法也差不多。可以看到,虽然A有try catch对,但是在回调过程中,如果B发生了错误,那么A是不会报错的。只是在回调函数funtion(err, result)中,有相关的错误信息。
第二个问题是回调函数使得代码的执行顺序不再线性,有可能会造成逻辑混乱。还是拿上面的程序举例,稍微修改下
try{ // A的第一块代码 req.models.vote.create(record, funtion(err, result){ // 回调函数 if (err) { // blablabla... // 对B执行结果的异常处理 } // A需要完成的接下来的任务 }) // A的第二块代码 // blablabla... // A的第三块代码 // blablabla... }catch(err){ // A的异常处理 }
上面这段程序,A在执行第一块代码时,把一个任务交给B去处理。关键是,之后A会按顺序执行下面的代码,第二块代码,第三块代码… 以此类推。那么问题来了,回调函数有可能先于代码块2被执行,也有可能晚于代码块2.那么如果代码块2和回调函数调用了同一个资源,就很有可能会报错。我在写的时候就碰到过一个,使得对一个http请求重复返回了2次内容,但是一个http只能有一个返回呀,于是就报错了。
解决的办法,就是将A后续的代码都放进回调函数中。或者对于两个并行的逻辑,尽量使用if-else逻辑,而不要用if-return逻辑。如下所示
// --------------------------------------------------- // 【将A后续代码放入回调函数中】 req.models.vote.create(record, funtion(err, result){ // 回调函数 if (err) { // blablabla... // 对B执行结果的异常处理 } // A的第二块代码 // A的第三块代码 // .. }) // --------------------------------------------------- // 【尽量使用if-else逻辑】 // 这样就只能执行A,B中的一个,而不会同时执行,导致报错 if ( logic 1 ){ // 回调函数A return } else { // 回调函数B return } // --------------------------------------------------- // 【不要使用下面这种方法】 // 看似能够精简代码,实则有可能会导致A和B都执行 if ( logic 1 ){ // 回调函数 A return } //回调函数 B return
第三个问题,频繁使用回调会使得代码逻辑一片混乱,嵌套过深,可读性和可维护性都非常糟糕。被称作”callback hell”。比如有一个业务逻辑,需要读取一次网页,然后读取若干次数据库。。。于是你的函数就变成这样了。。。
req.models.vote.create(record, funtion(err, result){ // 回调函数B if (err) { // blablabla... // 对B执行结果的异常处理 } req.models.xxx.find(..,function(err,result){ // 回调函数C if (err){ // 对C执行结果的异常处理 } req.models.xxx.find(..,function(err,result){ // 回调函数D if (err) {..} }) }) })
如上所示,不停的嵌套嵌套嵌套。。。。画面太美不敢看。。这时候为了让代码的逻辑更加清晰,需要使用中间件。在express中,是可以使用中间件来处理业务逻辑的。(其他的我不太清楚,应该也是有的)。所谓的中间件有点类似于linux中的管道,前一个函数执行完以后,如果没有返回,就由下一个函数处理。如下所示。(以express应用为例)
// 【router.js】 var test = require('./test.js') app.post('/',test.a,test.b) ; // 【test.js】 module.exports.a = function(req,res,next){ //必须有这三个变量 req.models.vote.create(record, funtion(err, result){ // 回调函数B if (err) { // blablabla... // 对B执行结果的异常处理 return res ; //返回http请求,不进入下一单元 } // 一些非异步的操作.. next() ; // 如果后面还有中间件,则next表示传给下个中间件 } } ; module.exports.b = function(req,res,next){ req.models.vote.create(record, funtion(err, result){ // 回调函数B if (err) { // blablabla... // 对B执行结果的异常处理 return res ; } // 一些非异步的操作.. return res ; // 如果是最后一个中间件,则不能有next函数,不然会导致无响应 } } ;
每个中间件的参数都是req,res,next. req中有一些请求的必要信息,以及有可能有上一个中间件的执行结果,res表示要返回给客户端的内容,next表示调用下一个中间件,只能在非结尾的中间件中使用
相关文章推荐
- NodeJS测试实例
- 使用 Jasmine 测试 Node 项目
- 前端小白学习Node.js的笔记
- 在Node.js 中用 Q 实现Promise – Callbacks之外的另一种选择
- node的学习过程(菜鸟)
- (OK) 交叉编译node-v4.2.1—for—android
- 24. Swap Nodes in Pairs
- 92. Reverse Linked List II
- 237. Delete Node in a Linked List
- Node.js中,q在链式调用和异步调用中起到的作用
- Windows 10 下安装 npm 后全局 node_modules 和 npm-cache 文件夹的设置
- 作用域与闭包
- Node
- 【转】如何使用NPM来管理你的Node.js依赖
- nodejs在线xlsx转json
- NodeJS 回调函数中的this
- Node.js学习
- file_operations -- file -- inode
- H5+MUI+Node.js+Socket.io群组即时聊天+发送图片+图片压缩
- H5+MUI+Node.js+Socket.io实现即时聊天以及发送+图片压缩