2015-12-03 121 views
1

我試圖使用q承諾庫在目錄中獲取.json文件的名稱並返回這些文件的內容。我能夠獲取文件名,但我無法使用arr.map與promise,以便讀取文件的內容。我希望getContents()能夠返回一個帶有指定文件名內容的映射數組。在地圖上使用q承諾獲取文件內容

function readDir() { 
    var deferred = q.defer(); 
    fs.readdir('users', function(err, data) { 
     if (err) console.log(err); 
     deferred.resolve(data); 
    }) 
    return deferred.promise; 
} 

function getContents(filenames) { 
    return filenames.map(function(filename) { 
     fs.readFile('users/' + filename, 'utf8', function(err, result) { 
      return result; 
     }); 
    }); 
} 

readDir() 
    .then(getContents) 
    .then(function(fileContents) { 
     // currently returns undefined 
     console.log(fileContents); 
    }); 

我怎樣才能正確地包裹getConents()的承諾,使我的數組中的內容不等於不確定?

回答

1

首先,您需要獲得一組承諾 - return result在異步回調中無用。作出承諾爲每一個readFile電話:

filenames.map(function(filename) { 
    return Q.nfcall(fs.readFile, 'users/' + filename, 'utf8'); 
// ^^^^^^ here's where the return is needed 
}) 

Q.nfcall function基本上沒有,你已經在你的readDir功能寫出同樣的東西。

現在,你有承諾的數組,你可以很容易地把它轉換成一個承諾爲陣列(等待着所有的人)使用Q.all

function getContents(filenames) { 
    return Q.all(filenames.map(function(filename) { 
     return Q.nfcall(fs.readFile, 'users/' + filename, 'utf8'); 
    })); 
} 
+0

是否有使用'JSON.parse()來'對結果的簡單方法'Q.nfcall()'? – Himmel

+1

只要執行'Q.nfcall(...).then(JSON.parse)'(就像每個其他承諾爲JSON文本一樣) – Bergi

0

首先,你可以定義使用承諾的fs.readFile的正確異步版本:

function readFileAsync(/* ...args */) { 
    return Q.nfapply(fs.readFile, arguments); 
} 

之後,您有兩個選項。這將在並行讀取文件:

function getContents(filenames) { 
    return Q.all(
     filenames.map(function(filename) { 
      return readFileAsync('users/' + filename, 'utf8'); 
     }) 
    ); 
} 

,這將讀取逐一:同時仍使用

function qMap(array, selector) { 
    var i = 0; 
    var result = []; 


    function store(x) { 
     result.push(x); 
     return next(); 
    } 

    function next() { 
     if (i < array.length) { 
      var index = i++; 
      var item = array[index]; 
      return Q.fcall(selector, item, index).then(store); 
     } else { 
      return result; 
     } 
    } 

    return Q.fcall(next); 
} 

function getContents(filenames) { 
    return qMap(filenames, function(filename) { 
     return readFileAsync('users/' + filename, 'utf-8'); 
    }); 
}