2017-09-24 333 views
0

我試圖圍繞Promises和如何在異步循環中使用它們。如何使用Promise.all()和異步循環?

我收集了下面的代碼讀取的三個文件(使用forEach),當所有的承諾內容解析記錄所有文件的輸出:

var Promise = require('bluebird'); 
var fs = require('fs'); 
var path = require('path'); 

var files = ['1.json','2.json','3.json']; 
var promises = [] 

files.forEach(function(file){ 
    fs.readFile(path.join('./',file), 'utf8', function(err,data){ 
     promises.push(new Promise(function(resolve, reject){ 
      resolve(data) 
     }) 
       ); 
    }) 
}); 

Promise.all(promises).then(function(values){ 
    console.log(values) 
}); 

我不知道如何把內環路.all()

我試過這段代碼,但是這記錄了一個空的數組。

我在做什麼錯?

+1

一)不使用'forEach'(但更好'map') b)你'*'推動諾言異步,當'Promise.all'接收它時,數組是空的。立即構建承諾,並且只異步解析* – Bergi

回答

0

使用.map()來迭代您的數組,啓動每個數組的異步調用,然後爲每個調用返回承諾。該地圖的返回值將是一組新的承諾,然後您可以將其傳遞給Promise.all()

let Promise = require('bluebird') 
let fs = Promise.promisifyAll(require('fs')) 

let promises = files.map((file) => { 
    // readFile will return promises because of bluebird promisifyAll 
    return fs.readFile(...) 
}) 

Promise.all(promises).then((results) => { 
    // results will be an array of all the files that were read 
    console.log(results); 
}); 
3

你混合回調與承諾,創建使用Array#map承諾的數組,並把它傳遞給Promise.all

var files = ['1.json', '2.json', '3.json']; 
var promises = files.map(file => { 
    return new Promise((resolve, reject) => { 
    fs.readFile(path.join('./',file), 'utf8', (err, data) => { 
     if (err) { 
     return reject(err); 
     } 
     resolve(data); 
    }); 
    }); 
}); 

Promise.all(promises).then(function(values){ 
    console.log(values) 
}); 
+0

好!謝謝。另一個問題。如果文件名數組的源自身是異步函數的結果,該代碼如何改變? – medicengonzo

+0

在這種情況下,您需要將加載文件名的函數添加到承諾鏈(從此函數開始承諾鏈):getFilesNames()。then(fileNames => Promise.all(fileNames.map(...)) ).then(values => ...)' – alexmac

+0

因此,我可以定義函數之前,然後只是調用它?另外,它應該返回一個承諾,對嗎? – medicengonzo