1. 不要使用 "try ... catch" ,因为nodejs都是异步操作,try catch无法捕捉回调里面的异常,除非你在回调里面也写try catch
try...catch statement cannot catch the error in callback. Here is an example:fs = require('fs');
try {
fs.stat('doesnt_exist.txt', function(err, stats) {
if (err) {
throw err;
}
console.log('data', stats);
});
}
catch (e) {
console.error('error statting');
}
这里的错误不会被捕捉。
解决方案
- 把数据库查询或者文本读取的try catch改为处理回调函数里面的第一个参数err,因为这些操作如果出错在nodejs里面是不会跑出异常而是返回一个err对象
- 使用forever https://github.com/nodejitsu/forever 这样进程挂掉就会被立马再次启动起来,记得设置 spinSleepTime !否则你的程序在1s内挂两次就再也启动不起来了
- 官方建议使用domain对象,如果是使用express的朋友可以直接使用 express-domain-middleware,这个插件有几个好处
a 捕获系统中所有的异常,并且可以自己定义出错的解决逻辑
b 在所有的流程中都会增加一个requestid,可以通过这个id在日志中体现出一个请求所经过的流程,解决了异步操作通过日志无法识别某个请求的问题
process.on('uncaughtException', function(err) {
console.error(err.stack);
});
这个方法在捕捉未考虑到的异常方面,万无一失,但是对于程序来说不是一个好习惯,我也不推荐
2. 避免使用 this 和 new
因为 Node.js 传递很多回调和有很多高阶函数,所以你要博阿正你的程序能在别的地方被调用的时候不会出问题,尽量不要用跟上下文相关的 this 和 new
3. 更小的函数块
尽量不要陷入“回调地狱”,让函数更小// 一个回调嵌套回调的例子
function convertJsonToCsv(filename, target, callback) {
readFile(filename, function (err, content) {
if (err) {
return callback(err);
}
parseJson(content, function (err, data) {
if (err) {
return callback(err);
}
convertToCsv(data, function (err, csv) {
if (err) {
return callback(err);
}
writeFile(target, csv, callback);
});
});
});
}
// 切分成小块之后
function convertJsonToCsv(filename, target, callback) {
readJsonFile(filename, function (err, data) {
if (err) { return callback(err); }
writeCsvFile(target, data, callback);
});
}
function readJsonFile(filename, callback) {
readFile(filename, function (err, content) {
if (err)
{ return callback(err); }
parseJson(content, callback);
});
}
function writeCsvFile(target, data, callback) {
convertToCsv(data, function (err, csv) {
if (err) { return callback(err); }
writeFile(target, csv, callback);
});
}
4. 避免加入上下文的变量
如果混入了函数以外的变量,那么在这个函数在别的地方被调用的时候就会出现不可预见的结果var CACHE = {};
function getRecord(id, callback) {
if (CACHE[id])
{ return CACHE[id]; }
http.get('http://foo/' + id, callback);
}
//别人在用这段代码的时候容易忘记CACHE变量
function getMyRecord(user, callback)
{ getRecord('record-' + user.id, callback); }
5. 总是对err参数编写相应的错误处理函数
忘记处理err变量可以视为是一种bug//Wrong code:
function writeCsvFile(target, data, callback) {
convertToCsv(data, function (err, csv)
{ writeFile(target, csv, callback); }
);
}
//Right code:
function writeCsvFile(target, data, callback) {
convertToCsv(data, function (err, csv) {
if (err)
{ return callback(err); }
writeFile(target, csv, callback);
});
}
注意 : 记得返回callback函数,以下的写法会造成虽然callback被调用了,但是代码还是继续执行下去了
if (err)
{ callback(err); }
6. 永远不要使用 with 或者 eval
7. 用 === 代替 ==
8. 声明变量的时候总是带 var
不要污染 global 范围的变量9. 回调函数总是把err参数作为第一个变量,如果参数中有回调函数,总是放在最后
比如 callback(err, param1, param2, callback)PS:更详细的 Node.js 代码规范见:
https://github.com/felixge/node-style-guidehttp://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
Reference:
http://geoff.greer.fm/2012/06/10/nodejs-dealing-with-errors/
http://stackoverflow.com/questions/5495984/coding-style-guide-for-node-js-apps