I'm trying to wrap my head around Promises and how to use them on async loops.
I gathered the following code to read the contents of three files (using forEach
) and when all promises resolve log the output of all files:
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)
});
I don't know how to put the loop inside the .all()
I tried this code but this logs an empty array.
What am I doing wrong?
I'm trying to wrap my head around Promises and how to use them on async loops.
I gathered the following code to read the contents of three files (using forEach
) and when all promises resolve log the output of all files:
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)
});
I don't know how to put the loop inside the .all()
I tried this code but this logs an empty array.
What am I doing wrong?
Share Improve this question asked Sep 24, 2017 at 22:13 medicengonzomedicengonzo 5192 gold badges10 silver badges23 bronze badges 2-
1
a) don't use
forEach
(but bettermap
) b) you'repush
ing the promise asynchronously, the array is empty whenPromise.all
receives it. Construct the promise immediately, and onlyresolve
it asynchronously – Bergi Commented Sep 24, 2017 at 22:16 - this article has it, nicely described medium./@bluepnume/… – MartianMartian Commented May 20, 2018 at 8:40
2 Answers
Reset to default 5You're mixing callbacks with promises, create an array of promises using Array#map
and pass it to 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)
});
Use .map()
to iterate over your array, starting an async call for each, then returning the promise for each call. The return value from that map will be a new array of promises which you can then pass to 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);
});