所有的模塊接口應(yīng)該遵循 優(yōu)先暴露錯(cuò)誤 這一原則。如下代碼所示,
module.exports = function (dragonName, callback) {
// do some stuff here
var dragon = createDragon(dragonName);
// note, that the first parameter is the error
// which is null here
// but if an error occurs, then a new Error
// should be passed here
return callback(null, dragon);
}
為了更好的理解這一原則,下面我們給出一個(gè)反例,
// this example is **BROKEN**, we will fix it soon :)
var fs = require('fs');
function readJSON(filePath, callback) {
fs.readFile(filePath, function(err, data) {
callback(JSON.parse(data));
});
}
readJSON('./package.json', function (err, pkg) {
// do something
}
當(dāng)fs.readFile
在執(zhí)行拋出一個(gè)Error
時(shí),方法readJSON
將不會(huì)按照代碼的期望運(yùn)行下去了。
我們對(duì)齊進(jìn)行修正,代碼如下,
// this example is **STILL BROKEN**, we are fixing it!
function readJSON(path, callback) {
fs.readFile(filePath, function(err, data) {
// here we check, if an error happened
if (err) {
// yep, pass the error to the callback
// remember: error-first callbacks
callback(err);
}
// no error, pass a null and the JSON
callback(null, JSON.parse(data));
});
}
這里,我們fs.readFile
的回調(diào)中優(yōu)先檢查err
對(duì)象,根據(jù)err
的值進(jìn)行不同的處理。
上面的代碼仍然有一個(gè)問(wèn)題,就是當(dāng)回調(diào)中檢查到err
對(duì)象不為空時(shí),代碼運(yùn)行完if
分支之后并不會(huì)停下,而是繼續(xù)運(yùn)行下去。這是因?yàn)槲覀冊(cè)谙鄳?yīng)的地方添加返回,這可能將會(huì)帶來(lái)一些不可預(yù)料的異常。所以,一般來(lái)說(shuō),我們都會(huì)直接return
回調(diào)。
// this example is **STILL BROKEN**, we are fixing it!
function readJSON(path, callback) {
fs.readFile(path, function(err, data) {
if (err) {
return callback(err);
}
return callback(null, JSON.parse(data));
});
}
此處有坑出沒(méi)!當(dāng)JSON.parse
方法不能正確的把一個(gè)字符串解析成json對(duì)象時(shí),它可能會(huì)拋出一個(gè)exception
。
因?yàn)?code>JSON.parse是一個(gè)同步方法,我們可以簡(jiǎn)單的使用一個(gè)try-catch
語(yǔ)句塊將其包裝起來(lái)。如下所示,
// this example **WORKS**! :)
function readJSON(path, callback) {
fs.readFile(path, function(err, data) {
var parsedJson;
// Handle error
if (err) {
return callback(err);
}
// Parse JSON
try {
parsedJson = JSON.parse(data);
} catch (exception) {
return callback(exception);
}
// Everything is ok
return callback(null, parsedJson);
});
}
注意 永遠(yuǎn)不要給異步方法(異步回調(diào))添加try-catch
,因?yàn)橐东@一個(gè)未來(lái)才會(huì)執(zhí)行到的函數(shù)所拋出的錯(cuò)誤是不可能的。
this
以及new
在Node.js中嘗試綁定一個(gè)特定的上下文環(huán)境給運(yùn)行環(huán)境不是好的主意,因?yàn)镹ode.js本身就是以使用回調(diào)函數(shù)及高階函數(shù)為一大特色。它推薦的編程風(fēng)格就是使用函數(shù)式的編程風(fēng)格和思想。
當(dāng)然,在有些場(chǎng)景下,使用基本原型、對(duì)象等編程手段將會(huì)更加有效率。但是如果可能的話,應(yīng)該盡量避免這種思路,使用Node.js推薦的風(fēng)格。
把問(wèn)題分解成一個(gè)個(gè)簡(jiǎn)單的小問(wèn)題是一個(gè)好的思路(the unix-way)。
Developers should build a program out of simple parts connected by well defined interfaces, so problems are local, and parts of the program can be replaced in future versions to support new features.
始終應(yīng)該遵循這樣一個(gè)原則, 不要一個(gè)模塊包含過(guò)多的功能,應(yīng)該盡量保持簡(jiǎn)單和功能單一化 。
建議使用已有的成熟的異步處理模塊來(lái)書(shū)寫(xiě)代碼。
(譯者:這部分的內(nèi)容感覺(jué)好low,感覺(jué)沒(méi)有存在的意義。)
錯(cuò)誤處理可以分為兩大類, 操作性錯(cuò)誤(operational errors) 和 代碼錯(cuò)誤(programmer errors) 。
操作性錯(cuò)誤可能發(fā)生在一些書(shū)寫(xiě)的很好的代碼中,因?yàn)樗鼈儾⒉皇莃ug,而是一些由于系統(tǒng)或者網(wǎng)絡(luò)等原因?qū)е碌膯?wèn)題,比如,
下面是解決操作性錯(cuò)誤的常規(guī)做法,
代碼錯(cuò)誤就是程序bug!你可以通過(guò)如下幾種方式來(lái)避免它們,
undefined
上讀取一個(gè)屬性因?yàn)檫@些都是程序bug,將會(huì)導(dǎo)致你的程序直接崩潰,而且你還不知道何時(shí)何地將會(huì)導(dǎo)致你的程序潰崩。所以當(dāng)這類錯(cuò)誤發(fā)生導(dǎo)致程序崩潰時(shí),我們使用一個(gè)守護(hù)進(jìn)程重啟你的程序。比如,supervisord或者monit。
npm init
來(lái)開(kāi)始一個(gè)新項(xiàng)目npm init
可以幫助你自動(dòng)生成應(yīng)用的package.json
文件。它將某些字段設(shè)為默認(rèn)值,當(dāng)然你后面可以手動(dòng)修改。
所以,當(dāng)你開(kāi)始一個(gè)新項(xiàng)目時(shí),應(yīng)該像下面這樣,
mkdir my-awesome-new-project
cd my-awesome-new-project
npm init
start
和test
腳本在你的package.json
中你可以在scripts
部分做一些腳本設(shè)置。npm init
命令會(huì)默認(rèn)生成start
和test
部分對(duì)npm start
和npm test
命令進(jìn)行支持。
此外,你還可以自定義可運(yùn)行的腳本設(shè)置, npm run-script <SCRIPT_NAME>
。
無(wú)論是生產(chǎn)環(huán)節(jié)還是開(kāi)發(fā)環(huán)境的部署都應(yīng)該帶有相應(yīng)的環(huán)境變量。一般性的做法是設(shè)置NODE_ENV
環(huán)境變量。
使用nconf模塊你可以根據(jù)不同的環(huán)境加載你自定義的環(huán)境配置。
當(dāng)然,你也可以使用內(nèi)置的process.env
對(duì)象來(lái)重置你的環(huán)境配置。
建議優(yōu)先使用已有的成熟的模塊或者解決方案。NPM上面有大量的模塊,總會(huì)找到你需要的模塊的。
使用統(tǒng)一的代碼風(fēng)格,無(wú)論你的代碼量多么的龐大,都是相對(duì)容易閱讀的。統(tǒng)一的代碼風(fēng)格一般包含, 縮進(jìn)規(guī)則 , 變量命名規(guī)則 等等。
這里有一份參考,RisingStack‘s Node.js Style Guide。
我希望這篇文章能夠讓你在Node.js的世界中少走一些彎路。
balabalabalabala…
更多建議: