#javascript #node.js #promise #async-await
#javascript #node.js #обещание #асинхронный-ожидание
Вопрос:
В настоящее время я разрабатываю программу, в которой мне нужно использовать Promise.all для одновременного запуска нескольких функций. Но прежде чем я смогу продолжить выполнение задачи, мне нужно завершить ТОЛЬКО 2 обещания, а затем запустить .then(), как мне это сделать?
Пример:
await Promise.all([Task1(),Task2(),Task3(),Task4(),Task5()]);
Мне это нужно для продолжения кода, когда только (например) Задача 1 и задача 4 завершены.
Я пытался поэкспериментировать, используя цикл ожидания завершения задач1 и задач2 с помощью переменных настроек на финише, но это. не работает вообще.
Комментарии:
1. Могут ли это быть любые два?
2. @T.J.Crowder Это 2 конкретных обещания, просто выбранных случайным образом для примера.
3. Тогда почему бы не передать только две функции вместо всех четырех?
4. @SamH — Опять же, могут ли это быть любые два (например, первые два, которые заканчиваются)? Или вы имеете в виду два конкретно?
5. Миссия состояла в том, чтобы выполнить все 5 задач одновременно с помощью Promise.all (потому что для их завершения требуется время, секунды) Иногда некоторые задачи могут занимать больше времени, чем другие, поэтому я все еще хочу продолжать ждать других обещаний, продолжая выполнение другой задачи, когда завершатся задачи Task1 и Task4. @T.J.Crowder
Ответ №1:
В комментарии вы, кажется, сказали, что заранее знаете, какие два являются более срочными, чем остальные (и что в этом примере это 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] = resu<
if ( counter >= min) {
resolve(results);
}
},
reject
);
}
});
}
Живой пример:
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] = resu<
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);
});
Ответ №2:
Один из способов сделать это — создать новый массив рандомизированных обещаний, а затем дождаться только их:
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
});
Ответ №3:
Я видел подобные трюки: Promise.all(promises.map(p => p.catch(() => undefined)));
довольно небезопасно.
Оригинальный ответ: здесь
Ответ №4:
Хорошо, как я вас понимаю, вы хотите сделать что-то вроде
const importantOnes = [Task1(), Task2()];
const remainingOnes = [Task3(), Task4(), Task5()];
const priorityPromise = Promise.all(importantOnes);
priorityPromise.then(doPriorityStuff);
Promise.all([priorityPromise, ...remainingOnes]).then(processTheCompleteData);
Ответ №5:
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