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

22,040

Solution 1

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]) {

  });

Solution 2

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:

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.

Share:
22,040
CrazySynthax
Author by

CrazySynthax

Updated on April 30, 2020

Comments

  • CrazySynthax
    CrazySynthax almost 4 years

    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.

  • CrazySynthax
    CrazySynthax over 7 years
    thanks. And what about my second question? Now, result includes all the data from both files. How can get each file's data to a separate array?
  • CrazySynthax
    CrazySynthax over 7 years
    thanks. Isn't there any way to do it without bluebird ?
  • rsp
    rsp over 7 years
    @CrazySynthax No. A standard Promise has only then which gets an array for Promise.all.
  • CrazySynthax
    CrazySynthax over 7 years
    and if I use 'spread', how is error handling being committed? I didn't see a catch clause in the link.
  • rsp
    rsp over 7 years
    @CrazySynthax You use .spread(...).catch(...) just like you would .then(...).catch(...).
  • rsp
    rsp over 7 years
    @CrazySynthax See the Bluebird cheatsheet