nodejs毀掉地獄是一直被人詬病的,如下總結一下解決毀掉地獄的一些方法。(暫時研究的比較淺)html
1.promisenode
promise模式在任什麼時候刻都處於如下三種狀態之一:未完成(unfulfilled)、已完成(resolved)和拒絕(rejected)。以CommonJS Promise/A 標準爲例,promise對象上的then方法負責添加針對已完成和拒絕狀態下的處理函數。then方法會返回另外一個promise對象,以便於造成promise管道,這種返回promise對象的方式可以支持開發人員把異步操做串聯起來,如then(resolvedHandler, rejectedHandler); 。resolvedHandler 回調函數在promise對象進入完成狀態時會觸發,並傳遞結果;rejectedHandler函數會在拒絕狀態下調用。(其中rejectedHandler可選)。promise
如下爲一個有幾級嵌套的函數,看起來比較使人噁心。(若是換成縮進四個字符可想而知)markdown
'use strict'; const md = require('markdown-it')(); const fs = require('fs'); fs.watchFile('nodejs.md', (curr, prev) => { let mdStr = fs.readFile('./nodejs.md', 'utf-8', (err, data) => { let mdData = md.render(data); let htmlTemplate = fs.readFile('./index.html', 'utf-8', (err, data) => { let html = data.replace('{{content}}', mdData); console.log(mdData); fs.writeFile('./nodejs.html', html, 'utf-8', (err, data) => { if (err) { throw err; } else { console.log('OK'); } }); }); }); });
一下用promise的方式實現一樣的效果,首先把異步函數封裝一下,而後下面能夠指教調用。可能看起來代碼比以前的版本更多,可是封裝的異步函數是能夠複用的。等任務多了就不顯得代碼多了。(但看最後調用函數的部分是否是優雅了很多)異步
'use strict'; const fs = require('fs'); const md = require('markdown-it')(); var Q = require('q'); function fs_readFile(file, encoding) { var deferred = Q.defer(); fs.readFile(file, encoding, function(err, data) { if (err) deferred.reject(err); // rejects the promise with `er` as the reason else deferred.resolve(data) // fulfills the promise with `data` as the value }); return deferred.promise; // the promise is returned } function fs_writeFile(file, data, encoding) { var deferred = Q.defer(); fs.writeFile(file, data, encoding, function(err, data) { if (err) deferred.reject(err); // rejects the promise with `er` as the reason else deferred.resolve(data); // fulfills the promise with `data` as the value }); return deferred.promise ;// the promise is returned //return 1; // the promise is returned } function fs_watchFile(file, curr, prev) { var deferred = Q.defer(); fs.watchFile(file, function(curr, prev) { if (!prev) deferred.reject(err); // rejects the promise with `er` as the reason else deferred.resolve(curr); // fulfills the promise with `data` as the value }); return deferred.promise // the promise is returned } function markdowm_convert(file, encoding, mdData) { var convertData = md.render(mdData); console.log(convertData); var deferred = Q.defer(); fs.readFile(file, encoding, function(err, data) { if (err) deferred.reject(err); // rejects the promise with `er` as the reason else { data = data.replace('{{content}}', convertData); deferred.resolve(data); // fulfills the promise with `data` as the value } }) return deferred.promise; // the promise is returned } // ===============promise實現 ===================== fs_watchFile('nodejs.md') .then(function() { return fs_readFile('./nodejs.md', 'utf-8'); }) .then(function(mdData) { return markdowm_convert('./index.html', 'utf-8', mdData); }) .then(function(data) { fs_writeFile('./nodejs.html', data, 'utf-8'); });
2.asyncasync
node的async包有多的數不清的方法我暫時只實驗了一個waterfall函數
waterfall瀑布流的意思和async中另外一個函數series差很少都是按照順序執行,不一樣之處是waterfall每執行完一個函數都會產生一個值,而後把這個值給下一個函數用。源碼分析
如下是嵌套了兩級的讀寫文件程序學習
fs.readFile('01.txt','utf-8',function(err,date){ fs.writeFile('02.txt',date,'utf-8',function(err,date){ console.log('複製完了'); }); })
用async.waterfall 後代碼以下ui
async.waterfall([ function(cb){ fs.readFile('01.txt','utf-8',function(err,result){ cb(err,result); }); },function(result,cb){ fs.writeFile('02.txt',result,'utf-8',function(err,result){ cb(err,result); }); } ],function(err,result){ console.log('複製完了'); })
另外最近學習了generator及node co庫的源碼分析。詳見這裏