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://*.com/questions/5495984/coding-style-guide-for-node-js-apps