Результаты Stream Promise клиенту по мере их разрешения в Promise.all - PullRequest
0 голосов
/ 10 января 2019

В Node я использую Promise.all от Bluebird для асинхронного выполнения Обещаний. Я не хочу ждать выполнения всех обещаний, прежде чем отправлять результаты обратно клиенту; скорее я хотел бы передать результат каждого Обещания, как только оно разрешится. Это возможно? Мое исследование показывает, что это не так, но я подумал, что стоит обратиться к сообществу.

Вот код (без попытки реализовать потоковую передачу):

async bulkExecution(req, res) {
    try {
        const { assets } = req.body;

        let thePromises = _.map(assets, (asset) => {
            return onePromise(asset);
        });

        // I want to stream each Promise result to client as it resolves
        let results = await Promise.all(thePromises);

        return res.status(200).send(results);
    } catch (err) {
        return res.status(500).send(err);
    }
}

1 Ответ

0 голосов
/ 10 января 2019

Я думаю, вам нужно будет перебрать все обещания и сделать .then() для каждого обещания и написать частичный ответ, а затем закрыть ответ после выполнения всех обещаний. Нечто подобное должно работать. Порядок ответов может отличаться от порядка массива обещаний. Например, мой пример ниже вернет второе обещание первым.

let res = {
  write: (data) => {console.log(data)},
  end: () => {}
};

let promise1 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve('foo');
  }, 500);
});

let promise2 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve('foo');
  }, 300);
});

let promises = [promise1, promise2];

let count = 0;
promises.forEach((promise) => {
  promise.then((data) => {
    res.write(data);
    count++;
    if (count >= promises.length){
        res.end();
    }
  })
})

Изменено для записи в формате JSON.

let res = {
  write: (data) => {
    console.log(data)
  },
  end: () => {}
};

let promise1 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve({foo:"bar"});
  }, 500);
});

let promise2 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve({bar:"foo"});
  }, 300);
});

let promises = [promise1, promise2];

let count = 0;

res.write("[");
promises.forEach((promise) => {
  promise.then((data) => {
    res.write(JSON.stringify(data));
    count++;
    if (count >= promises.length) {
      res.write("]");
      res.end();
    } else {
      res.write(",");
    }
  })
})

Потоковая передача JSON, как это обычно не происходит, но может использоваться для уменьшения объема памяти, используемой сервером. Это потому, что вам не нужно создавать полный ответ в памяти перед отправкой ответа. Клиенту по-прежнему потребуется достаточно памяти для считывания всего объекта в память.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...