Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Promise.all in JavaScript: How to get resolve value for all promises?

I wrote the following node.js file:

var csv = require('csv-parser');
var fs = require('fs')
var Promise = require('bluebird');
var filename = "devices.csv";
var devices;

Promise.all(read_csv_file("devices.csv"), read_csv_file("bugs.csv")).then(function(result) {
    console.log(result);
});


function read_csv_file(filename) {
    return new Promise(function (resolve, reject) {
            var result = []
            fs.createReadStream(filename)
                .pipe(csv())
                .on('data', function (data) {
                    result.push(data)
                }).on('end', function () {
                resolve(result);
            });
    })
}

As you can see, I use Promise.all in order to wait for both operations of reading the csv files. I don't understand why but when I run the code the line 'console.log(result)' is not committed.

My second question is I want that the callback function of Promise.all.then() accepts two different variables, while each one of them is the result of the relevant promise.

like image 842
CrazySynthax Avatar asked Nov 16 '16 22:11

CrazySynthax


2 Answers

First question

Promise.all takes an array of promises

Change:

Promise.all(read_csv_file("devices.csv"), read_csv_file("bugs.csv"))

to (add [] around arguments)

Promise.all([read_csv_file("devices.csv"), read_csv_file("bugs.csv")])
// ---------^-------------------------------------------------------^

Second question

The Promise.all resolves with an array of results for each of the promises you passed into it.

This means you can extract the results into variables like:

Promise.all([read_csv_file("devices.csv"), read_csv_file("bugs.csv")])
  .then(function(results) {
    var first = results[0];  // contents of the first csv file
    var second = results[1]; // contents of the second csv file
  });

You can use ES6+ destructuring to further simplify the code:

Promise.all([read_csv_file("devices.csv"), read_csv_file("bugs.csv")])
  .then(function([first, second]) {

  });
like image 100
nem035 Avatar answered Oct 19 '22 19:10

nem035


Answer to your second question:

If you want the then callback to accept two different arguemnts, then you can use Bluebird and its spread method. See:

  • http://bluebirdjs.com/docs/api/spread.html

Instead of .then(function (array) { ... }) and having to access array[0] and array[1] inside of your then handler you will be able to use spread(function (value1, value2) { ... }) and have both variables named as you want.

This is a feature of Bluebird, it's not possible with plain Promise.

You use Bluebird just like Promise, e.g.:

var P = require('bluebird');
// and in your code:
return new P(function (resolve, reject) { ...
// instead of:
return new Promise(function (resolve, reject) { ...

Of course you don't have to name it P but whatever you want.

For more examples see the Bluebird Cheatsheets.

like image 32
rsp Avatar answered Oct 19 '22 19:10

rsp