2014-02-16 20 views
2

我開始學習JavaScript承諾,但我無法理解如何將Q函數應用於Node.js回調函數。在示例中使用承諾和Node.js函數

In similar question建議使用Q.denodeify(),但它適用於fs.readFile()並且不適用於fs.exists()

這是一個簡單的功能,在目錄中返回文件及其大小的列表:

function openDir(path, callback) { 
    path = __dirname + path; 
    fs.exists(path, function (exists) { 
     if (exists) { 
      fs.readdir(path, function (err, files) { 
       if (err) { 
        throw err; 
       } 
       var filesCounter = 0, 
        filesTotal = files.length, 
        result = []; 
       files.forEach(function (filename, index) { 
        fs.stat(path + filename, function (err, stats) { 
         if (err) { 
          throw err; 
         } 
         result[index] = {}; 
         result[index].name = filename; 
         result[index].size = stats.size; 
         if (++filesCounter === filesTotal) { 
          callback(result); 
         } 
        }); 
       }); 
      }); 
     } 
    }); 
} 

http.createServer(function (req, res) { 
    openDir('/', function (data) { 
     res.writeHead(200, { 
      'Content-Type': 'application/json; charset=utf-8' 
     }); 
     res.end(JSON.stringify(data)); 
    }); 
}).listen(1337, '127.0.0.1'); 

怎麼寫承諾使用此代碼(與Q或其他庫)?

+1

你可以看看我的要點,它使用非常相似的任務,它是用Q https://gist.github.com/riston/9022931寫的。 –

回答

6

fs.exists是一種無用的方法。它不返回節點樣式回調,通常可以省略。在你的例子中,你會處理從fs.readdir的錯誤。

fs.exists()是一個時代錯誤,只存在於歷史原因。 幾乎從來沒有理由在你自己的代碼中使用它。 node docs

這裏就是你們的榜樣符合Q返工,請注意,我們返回一個承諾,而不是統計推遲自己的錯誤處理給調用者。我列舉了一個如何使用Q.defer處理fs.exists的例子,以展示如何代理非節點樣式的回調。

var Q = require('q'); 
var fs = require('fs'); 
var http = require('http'); 
var readdir = Q.denodeify(fs.readdir); 

function stat(file){ 
    return Q.nfcall(fs.stat, file) 
     .then(function(stats){ 
      stats.filename = file; 
      return stats; 
     }); 
} 

function openDir(path) { 
    path = __dirname + path; 

    return readdir(path) 
     .then(function(files) { 
      return files.map(function(file){ 
       return stat(path + file); }); }) 
     .then(Q.all); 
}; 

// proxy fs.exists to return a promise. Example of Q.defer 
function exists(file){ 
    var deferred = Q.defer(); 
    fs.exists(file, function(result){ 
     return result ? deferred.resolve(file) : deferred.reject('invalid file');  
    }); 
    return deferred.promise; 
} 

http.createServer(function (req, res) { 
    openDir('/').done(
     function (data) { 
      res.writeHead(200, { 
       'Content-Type': 'application/json; charset=utf-8'}); 
      res.end(JSON.stringify(data)); 
     }, 
     function (err) { 
      res.writeHead(500, { 
       'Content-Type': 'application/json; charset=utf-8'}); 
      res.end(JSON.stringify({error: err})); 
     }); 
    }).listen(1337, '127.0.0.1');