一些我更願意在開始就知道東西
利用 Node.js 開發是一個非常有趣,和令人滿足的過程, 它有3萬多個模組可以選擇使用,並且所有的模組可以非常容易的整合入現有的應用之中。
無論如何,對於一些剛開始使用Node.js 開發的的人來說, 很容易碰壁,在這個文章中,我會提到在你學習過程中遇到的問題。
貼士 1: 在開發環境使用 nodemon, 在生產環境使用pm2
當你第一次開發Node.js應用的時候, 其中一件事情就是一次又一次的執行[file].js 就和揭傷疤一樣。 當我第一次開發的node app時候,這個讓我感到異常挫敗和痛苦, 尤其是每當我修改很小東西的時候需要control+c
幸運的是我發現了一個非常棒的工具Nodemon
。 你可以利用以下的命令來安裝
1 |
npm install -g nodemon |
Nodemon 是一個令人驚歎的工具, 當你全域性安裝它以後, 可以通過 nodemon [file].js 來啟動你的node.js scripts,它會告訴nodemon來監視你的script和scripts的所有變化, 這樣的Node.js開發方式非常震撼以及讓大大提高開發速度。
那麼,生產環境又如何, 除非你用了heroku
,Nodejitsu
或者其它一些好的 Node.js 平臺(也許它們有類似的功能), 但是碰巧你用了EC2 或者一些其它的雲平臺來執行你的Node.js app, 你如何能然保證這是一個始終執行的Node.js app
案就是PM2, PM2 是一個類似於Nodemon的工具,不同之處在於它用於生產環境, 和Nodemon相似的地方在於它會監控你的app的任何修改或者重新部署,但是有更好的一面, PM2 在遭遇到崩潰的時候,它會正確重啟你的app。
PM2的優勝之處在於當你要將app需要多核處理的時候,PM2內部整合的負載均衡可以讓你很容易的去指定執行多少個例項。
1 |
pm2 start app.js -i max |
-i
引數目的是指定執行多少個例項,在這個例子中 PM2 使用了一個常量max
來擴充套件你的app運轉到你最大的核數,不要忘記Node 平時只會執行在單核!
貼士 2: Async 或者 Q
當你專注於寫了更多的node.js apps的時候,你肯定領略了什麼是回撥地獄。 如果你還不知道,這裡有一個例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
function register(name, password, cb){ checkIfNameExists(name, function(err, result){ if(err){ return cb(“error”); } checkIfPasswordGood(password, function(err, result){ if(err){ return cb(“error”); } createAccount(name,password, function(err,result){ if(err){ return cb(“error”); } createBlog(name, function(err, result){ sendEmail(name, function(err, result){ callback(result); }); }); }); }); }); } |
這顯然不是一個有用或者令人折服的程式碼, 反而進入一種回撥地獄般兩難的境地,是你的話將如何避免
一個簡單的辦法是使用events, 但是我個人不建議這麼做,因為使用events來呼叫只有一個用途的私有方法,足以令人受挫
所以你該怎麼做 這裡有兩個編譯好的模組,async.js
和Q
, 它們兩個都可以防止落入回撥地獄
Async.js或者 ‘async’ 讓你可以容易的執行一些連續或者平行的任務,在不依賴一個又一個的巢狀迴圈前提下。
下面是一些來自Async的readme,寫明瞭它支援的模式, 如需獲取全部的支援方式請去它們的github主頁檢視。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
async.map([‘file1',’file2',’file3'], fs.stat, function(err, results){ // results is now an array of stats for each file }); async.filter([‘file1',’file2',’file3'], fs.exists, function(results){ // results now equals an array of the existing files }); async.parallel([ function(){ … }, function(){ … } ], callback); async.series([ function(){ … }, function(){ … } ]); async.waterfall([ function(callback){ callback(null, ‘one’, ‘two’); }, function(arg1, arg2, callback){ callback(null, ‘three’); }, function(arg1, callback){ // arg1 now equals ‘three’ callback(null, ‘done’); } ], function (err, result) { // result now equals ‘done’ }); |
如果我們用async的waterfall來修改之前的例子,結果將更加容易閱讀, 再也不用讓你的程式碼看起來像一個死亡金字塔。
另一個重要的庫叫做Q。 這個庫是一個暴漏promises的概念, Promise 是一個含有’promise’方法的返回物件,它提供了一個最終的返回值,非常優雅的將javascripts的非同步和node.js緊密聯絡在一起。
For example, taken from Q’s repo page.
1 2 3 4 |
promiseMeSomething() .then(function (value) { }, function (reason) { }); |
這個 promise me 方法 正確返回了一個物件, 物件將在傳入value的時候呼叫這個方法當,並且它提供了一個額外的callback來處理失敗後的返回值
這是一個非常有條理的方式來避免回撥地獄,如果你重寫我們之前的那個例子,你可以非常容易的讓這些函式正確被呼叫並執行。
就和我之前說的一樣, 我很不願建立只有一個用途的一堆功能,相反的在’then’之後傳入一個方法名,僅僅建立了一個匿名的內部功能和傳遞,當然了選擇權始終在你手裡。
總的來說,當你落入回撥地獄的時候,是時候去看看 async.js或者Q吧。
我的選擇 當然是 Q
貼士 3: 輕鬆除錯 Node.js apps
如果你從一個IDE重度整合的語言比如java 或者C# 轉來除錯Node.js, 你一定會感到很困擾, 大部分新加入node的開發者採用了’flow’的除錯模式,從這一刻開始你最好的朋友就是console.log
但是依然有更常見的除錯方式來代替, Node.js 內建了一個偵錯程式你可以稱為 node debug, 不過我更喜歡的 node-inspector
它們的github說 “Node Inspector 是一個使用Blink Developer Tools (以前稱為WebKit Web Inspector)node.js偵錯程式的介面,”
簡而言之,node-inspector 可以讓你用任何你想用的編輯器和chrome web tools來除錯你的應用,這是多麼的性感。
Node-inspector 可以讓你做一些非常酷的事情,比如實時修改,單步除錯,注入以及一堆其它非常酷的東西。
讓我們來根據指示一步一步安裝
https://github.com/node-inspector/node-inspector
貼士 4: Nodefly
一旦你有你的應用程式正常執行,你可能會問自己,你怎麼可以監視它的效能和配置檔案,以確保您的應用程式執行在最佳的速度。最簡單的答案是一個卓越的服務,我稱為Nodefly。
用簡單的一行程式碼Nodefly開始監視你的應用程式記憶體洩漏,測量redis用了多久,mongo查詢和一堆其它很酷的東西。
貼士 5: 利用NPM進行模組管理
Node做最常見的事情之一是通過NPM安裝軟體包。Node有一個驚人的包管理器安裝所有指定在你的package.json的manifest檔案中的模組。然而,所有初學者都會碰上保持的package.json檔案中您所使用的所有的模組都是最新版。
這似乎是一個痛苦的過程,總是開啟的package.json來更新新模組的依賴,但許多人不知道的是npm會為你做這個!
非常簡單執行 npm install – save module_name 然後 npm將自動更新你的package.json 包含正確的模組和版本,
1 |
npm install - save module_name |
貼士 6: 不要提交 node_modules 資料夾
雖然我們的話題一直是modules和npm,但是並不是不是很多人都知道,你不應該提交node_modules資料夾。這背後最大的原因是,沒有必要提交這個資料夾。只要有人下載你的程式碼,它們可通過執行NPM來安裝和下載所有需要的模組。
您可能會說,它是不是一個大問題,如果檢查node_modules,但是,如果下載程式碼的人使用了和你編譯modules不一樣的作業系統的來安裝通過NPM?你的應用程式將會崩潰,下載程式碼的人將不知道為什麼會如此!
舉個例子bcrypt
以及sentimental
如果當在您安裝在主機系統上編譯它們,因為它們用了本地C語言元件來編譯。
避免檢查node_modules資料夾的方式是加入.gitignore
1 |
// .gitignore node_modules/* |
貼士 7: 別忘記返回
初學者經常犯一個很常識的錯誤,就是忘記callback後的返回值,雖然有些時候,這沒有影響,有很多時候,你會遇到奇怪的問題,因為你的回撥被呼叫兩次。
讓我們看一個簡單的例子
1 2 3 4 5 6 |
function do(err,result, callback){ if(err){ callback(“error”); } callback(“good”); } |
乍一看,這個片段是有道理的。如果有錯誤,在回撥中傳送“錯誤。如果不傳送return,呼叫callaback後這個函式不會停下來。它只是將移動到呼叫回callback(“good”)。
這樣做在長期和複雜的程式碼行裡面會節省幾個小時的除錯。