如何用nodejs 把业务逻辑写的漂亮
背景:接触nodejs 写业务代码不久。 一直是phper
这个问题可能问的不是很恰当, 因为大部分时候可能代码写的好不好跟具体语言很多时候是无关的。
仅仅提出我的看法:
- 太多回调。 用回调倒是没关系,但是很多代码里回调是直接写的匿名函数。 匿名函数第一眼无法通过函数名理解其作用,其次是如果这个回调的匿名函数里如果逻辑太多,不利于重用。
- 异步, 显然用异步写的代码,肯定理解起来要困难。
- 很多函数会这样写
function (params, callback){ //...}
,把所有参数放到一个对象里传进去。因为总要留个参数位置给callback
, 要多写一个变量, 就会偷懒,把其他参数当作对象传递进去。 个人不是很喜欢这种作法,会让人猜不透这个函数有哪些变量?有什么作用?
大家会怎么去设计node的函数和回调,便于阅读理解?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
前段时间的项目使用了Nodejs,中间经过过一次重构,基于Express框架,分享一下经验:
基于Nodejs的回调语法,你会写出大量下面这种代码:
这就是所谓的 “回调黑洞” 了,采用回调写法最大的问题有两个:
一是异常问题的处理,假设你的
doAsync4
依赖doAsync3
的返回值,而doAsync3
函数又依赖于doAsync2
的返回值,如果doAsync2
函数没有返回预想的结果,那么回调仍会继续执行,而如果你的代码里没有做良好的错误处理,可能代码会一直执行到doAsync4
,debug的痛苦可想而知。二是业务流程的变更,现在我们假设要更改业务流程,
doAsync2
发生在doAsync1
之前,你的重构工作量有多少?这时我们就要考虑使用Promise了,我并不打算在这里详细的介绍Promise,有趣的是SF就有对于Promise分析良好的系列文章:深入理解Promise五部曲
以及目前常见的回调写法替代方案Node.js回调黑洞全解:Async、Promise 和 Generator
上述代码如果用Promise来重构结果会是这样的:
在应用中分出
Controller
层和Model
层,不要把页面渲染和逻辑都塞到Router
层。理想的结果是:Controller
+Model
+Router
+Filter
,Filter层即是过滤,也可以理解为中间件,可以写一些过滤规则,比如最常见的要求用户登录:在项目的上一次重构中,我砍掉了Router层,增加了一层API,将页面渲染和流程都放在Controller,而数据处理都在API,这样方便未来做数据验证和单元测验:
Controller层
API层
Model层取决于你用的数据库,流程的Promise化客观上要求了你的Model也要Promise化,Node上常见数据库的ORM都提供了Promise的写法,对应去看就好了。Express并不提供这种Restful路径的写法,我参考Rabbit框架(感谢芋头)基于这个插件改了改:rainbow
最后来看看成果,重构前的代码如下:
重构之后(数据都放在API层了):
那么问题来了,写Nodejs哪种写法强?
关于异步和回调,
Promise才是救世主
async.js是邪教
自己的业务逻辑一律用Promise表示结果,三方的库第一时间promisify,异常通过promise reject处理
顺便推荐Promise库bluebird
coffeescript和它派生的coco和LiveScript
晒最近刚写的一个简单小站代码 https://github.com/mcfog/higari
express, bluebird, 前后端分离,redis缓存
业务是爬虫扒别的站自己组织展示
下面是吐列表的一个controller,扒列表,循环扒详情组装好json输出
Wind.js
Async.js
promise can save your ass
promise co 多的是
说4个方案:1.把回调函数再模块化;2.Promise,用同步思想把异步封装(符合程序员的思维),衍生的有:Q,bluebird;3.eventproxy,事件式编程的思维;4.async,最后一步调用cb,处理错误,管理任务;
这里请忽略采用ECMAScript6的generator(node > v0.11.2)