Promise.all в JavaScript: как получить значение разрешения для всех promises?

Я написал следующий файл node.js:

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);
            });
    })
}

Как видите, я использую Promise.all, чтобы дождаться обеих операций чтения файлов csv. Я не понимаю почему, но когда я запускаю код, строка 'console.log(result)' не фиксируется.

Мой второй вопрос: я хочу, чтобы функция обратного вызова в Promise.all.then() две разные переменные, в то время как каждая из них является результатом соответствующего обещания.

Ответ 1

Первый вопрос

Promise.all принимает множество обещаний

Изменить:

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

(добавить [] вокруг аргументов)

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

Второй вопрос

Promise.all разрешается с массивом результатов для каждого из обещаний, которые вы передали ему.

Это означает, что вы можете извлечь результаты в переменные, такие как:

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
  });

Вы можете использовать ES6+ деструктурирующие для дальнейшего упрощения кода:

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

  });

Ответ 2

Ответьте на второй вопрос:

Если вы хотите, чтобы обратный вызов then принимал два разных аргумента, вы можете использовать Bluebird и его метод spread, См:

Вместо .then(function (array) { ... }) и для доступа к array[0] и array[1] внутри вашего обработчика then вы сможете использовать spread(function (value1, value2) { ... }) и иметь обе переменные, названные так, как вы хотите.

Это особенность Bluebird, это невозможно с простым Promise.

Вы используете Bluebird так же, как Promise, например:

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

Конечно, вам не нужно называть его P, но все, что вы хотите.

Дополнительные примеры см. в Bluebird Cheatsheets.