Node.JS
Node.js最佳实践
这是有关Node.js的代码风格 开发流程等实战中的最佳实践。这些最佳实践能够帮助你成为更好的Node.js开发人员,Node.js因为是基于事件的开发模式,不同于平常基于线程的顺序编程,如果按照老的传统的编程习惯编写Node.js代码会导致很多问题,Node.js成也回调败也回调,过多使用回调会陷入回嵌套调陷阱,代码难以阅读,同时,Node.js是单线程,适合非CPU耗费的应用,比如IO读写转发,网页浏览等等,如何避免一些CPU繁重代码导致整体堵塞也是编程中应该注意的问题。
代码风格篇
回调约定
模块应该首先暴露error-first错误优先的回调接口。
应该如下:
module
.exports
=function
(
dragonName
,callback
){
// 做一些事情
var
dragon
=createDragon(
dragonName
);
// 注意下面,第一个参数应该是抛出的错误error
//这里是空
// 如果有错误发生,抛出错误error
return
callback(null,
dragon
);
}
总是在回调函数中检查错误
为了解释这点,首先我们看看一个错误的案例,然后看问题出在哪里,如何解决它。
//这个案例是错的,我们稍后展示如何解决
varfs
=require('fs');
functionreadJSON(
filePath
,callback
){
fs
.readFile(filePath
,function(
err
,data
){
callback(
JSON
.parse(data
));
});
}
readJSON('./package.json',function
(
err
,pkg
){
...
}
readJSON函数的问题是没有检查错误,如果在执行时发生错误,你应该总要检查它们。下面是解决后的版本:
functionreadJSON(
filePath
,callback
){
fs
.readFile(filePath
,function(
err
,data
){
// 如果有错误发生,这里我们进行检查
if
(
err
){
// 将错误传递给callback函数
// 记住这就是: error-first callbacks
callback(
err
);
}
// no error, pass a null and the JSON
callback(null,
JSON
.parse(data
));
});
}
总是返回回调
上述代码还是有一个问题,如果有错误Error发生,那么执行if中的语句callback函数,如果这个这个callback函数一直执行下去不会停止或返回,那么就导致很多不可预料的事情发生,所以,我们必须增加一个return,回调必须返回,否则执行顺序走叉了,回不来了。
functionreadJSON(
filePath
,callback
){
fs
.readFile(filePath
,function(
err
,data
){
if
(
err
){
return
callback(
err
);//注意这里是返回
}
return
callback(null,
JSON
.parse(data
));//这里是返回
});
}
只在同步代码中使用try-catch
这里我们关注上面代码中有一个JSON.parse,这个函数在不能分析有效JSON格式情况下可能会抛出exception出错。
因为JSON.parse是同步发生,也就是执行到这个函数时,如果有错误就会立即发生,一旦发生就影响我们当前的主执行顺序,我们需要使用try-catch包住这段代码,注意,这只能在同步代码中使用,也就是主顺序代码中使用,在回调函数中使用是不会工作的,回调函数中出错是作为第一个参数返回,error-first callback。
functionreadJSON(
filePath
,callback
){
fs
.readFile(filePath
,function(
err
,data
){
var
parsedJson
;
// 处理 error
if
(
err
){
return
callback(
err
);
}
// 解析Parse JSON
try
{
parsedJson
=JSON
.parse(data
);
}
catch
(exception)
{
return
callback(
exception
);
}
// 一切ok
return
callback(null,
parsedJson
);
});
}
避免this和new
在Node中绑定特定的上下文场景是不好的,因为Node包含了很多回调函数的传送,大量使用高阶函数来管理控制流程,用函数风格会省去很多麻烦,当然,还是有很多情况使用prototypes 对象方式是有效的,但是如果可能还是要避免它们。
创建小的模块
以Unix方式来实现Node编码:
开发者建立程序时,应该是一一个个部分通过良好定义的接口连接在一起,这样问题会容易定位,程序的部分在将来需要支持新功能时能够替代。
不要建立Deathstars 死亡之星,只有瞬间的闪耀便消失了,一个模块应当只做一件事。
使用好的异步模式
推荐使用async框架
错误处理
错误处理分为操作错误和编程错误。
(一)操作错误:操作错误是运行时错误,也会发生在编写很良好的应用中,因为它们不是bug,而是系统或远程服务的问题,如:
- 请求过时
- 系统内存出错out of memory
- 无法连接到远程服务
那么如何处理操作错误呢?依赖于操作错误的类型,可以做以下几件事:
- 试图解决错误,如果文件丢失,你需要首先创建一个
- 重试操作,网络连接超时多试几次
- 当处理用户客户端的输入时告诉客户端,有些不正常,但是能用。
- 流程崩溃,比如应用无法读取配置文件等。
无论如何,进行日志记录和分析是最重要的。
(二)编程错误:编程错误是bug,下面情况你应该努力避免,如:
- 没有使用回调函数调用一个异步函数(无法异步函数处理错误)
- 不能读取错误:
undefined
解决编程错误是让它们早点出现,这些Bug你不知道将来会在什么时候出现,通过测试等让其尽早被发现,在运行生产环境,需要有一个流程控制系统能够在应用崩溃时重新启动应用,如 supervisord 或 monit.
下页