Как дождаться 2 обещаний в Promise.all, а затем выполнить другое задание - PullRequest
0 голосов
/ 10 апреля 2019

В настоящее время я разрабатываю программу, в которой мне нужно использовать Promise.all для запуска нескольких функций одновременно. Но прежде чем я смогу продолжить выполнение задачи, мне нужно ТОЛЬКО 2 обещания, чтобы закончить, а затем запустить .then (), как мне это сделать?

Пример:

await Promise.all([Task1(),Task2(),Task3(),Task4(),Task5()]);

Мне нужно, чтобы продолжить код, когда только (например) Задача 1 и Задача 4 завершены.

Я попытался поэкспериментировать, используя цикл while, ожидающий завершения задач Task1 и Task2 переменными настроек на финише, но это. не работает вообще.

Ответы [ 5 ]

3 голосов
/ 10 апреля 2019

В комментарии вы, кажется, сказали, что заранее знаете, что два из них более срочные, чем остальные (и что в этом примере это Task1 и Task4).

Тогда просто используйте Promise.all дважды:

const allResults = Promise.all([
    Promise.all([Task1(), Task4()])
    .then(([result1, result4]) => {
        // Those two are done, do what you like with `result1` and `result4`...
        return [result1, result4];
    }),
    Task2(),
    Task3(),
    Task5()
])
.then(([[result1, result4], result2, result3, result5]) => {
    // All five are done now, let's put them in order
    return [result1, result2, result3, result4, result5];
})
.then(/*...*/)
.catch(/*...*/);

Там я сохранил общий порядок 1, 2, 3, 4, 5 во внешней цепочке, переназначив порядок в общем обработчике then.


Первоначально я предполагал, что вы хотите подождать, пока не закончится любой два, а не конкретные два. Для этого нет встроенного, но достаточно просто написать:

function enough(promises, min) {
  if (typeof min !== "number") {
    return Promise.all(promises);
  }
  let counter = 0;
  const results = [];
  return new Promise((resolve, reject) => {
    let index = 0;
    for (const promise of promises) {
      let position = index++;
      promise.then(
        result => {
          results[position] = result;
          if (++counter >= min) {
            resolve(results);
          }
        },
        reject
      );
    }
  });
}

Live Пример:

function enough(promises, min) {
  if (typeof min !== "number") {
    return Promise.all(promises);
  }
  let counter = 0;
  const results = [];
  return new Promise((resolve, reject) => {
    let index = 0;
    for (const promise of promises) {
      let position = index++;
      promise.then(
        result => {
          results[position] = result;
          if (++counter >= min) {
            resolve(results);
          }
        },
        reject
      );
    }
  });
}

const delay = (ms, ...args) => new Promise(resolve => setTimeout(resolve, ms, ...args));
const rnd = () => Math.random() * 1000;

enough(
  [
    delay(rnd(), "a"),
    delay(rnd(), "b"),
    delay(rnd(), "c"),
    delay(rnd(), "d"),
    delay(rnd(), "e")
  ],
  2
)
.then(results => {
  console.log(results);
})
.catch(error => {
  console.error(error);
});
1 голос
/ 10 апреля 2019

Один из способов сделать это - создать новый массив рандомизированных обещаний, а затем ждать только таких:

let array = [Task1(),Task2(),Task3(),Task4(),Task5()];

// Select any two promises after running the randomization logic
let promises = Promise.all[array[1], array[3]];

promises
  .then(() => {
    // Do stuff here
  });
0 голосов
/ 10 апреля 2019

ОК, как я понимаю, вы хотите сделать что-то вроде

const importantOnes = [Task1(), Task2()];
const remainingOnes = [Task3(), Task4(), Task5()];
const priorityPromise = Promise.all(importantOnes);

priorityPromise.then(doPriorityStuff);
Promise.all([priorityPromise, ...remainingOnes]).then(processTheCompleteData);
0 голосов
/ 10 апреля 2019

Я видел такие трюки: Promise.all(promises.map(p => p.catch(() => undefined))); Впрочем, небезопасно.
Оригинальный ответ: здесь

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

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

Ваши задачи будут выполняться, как только вы создадите каждое Обещание.

Если вы хотите подождать после определенных задач, включите только эти задачи в Promise.all:

const tasks = [Task2(), Task3(), Task5()];
const result1 = await Promise.all([Task1(), Task4()]);
// Task1 and Task4 are done here
const result2 = await Promise.all(tasks);
// All remaining tasks are done here
...