Как выполнить prom.all для массива массива promises?
Я пытаюсь запустить массив функций параллельно, и когда все заканчивается, я хочу работать над этим результатом.
Я использую promises. Теперь я могу поместить все функции в массив и сделать
Promise.all(массив функций)
Но у меня есть массив вроде
[[promise1, promise2], [promise3,promise4], [promise5,promise6]],
где каждое обещание является обещаемой функцией.
В ссылочном документе Promise указано, что параметр в Promise.all должен быть итерируемым объектом, а мой массив - итерируемым.
Но это не работает для меня. Я думаю, что он выполняет [обещание1, обещание2] как обещание, но не индивидуальное обещание.
Может кто-нибудь, пожалуйста, помогите мне, как я могу это достичь или есть лучший способ?
Ответы
Ответ 1
Вам также необходимо вызвать Promise.all
для каждого элемента массива:
const promise4all = Promise.all(
promiseArray.map(function(innerPromiseArray) {
return Promise.all(innerPromiseArray);
})
);
Или напрямую:
// Fix: Promise.all.bind is required because it seems like Promise.all
// implementation relies on "this"
const promise4All = Promise.all(promiseArray.map(Promise.all.bind(Promise)))
// or
// const promise4All = Promise.all(promiseArray.map(p => Promise.all(p)))
Таким образом, внешний Promise.all
получает сгруппированные обещания в другом Promise.all
:
promise4all.then(function(promiseGroupResult) {
// promiseGroupResult is the actual result of each promise group
// and you'll be able to get each result this way: promiseGroupResult.somePropertyName
});
Ответ 2
Вы можете просто использовать Promise.all
для всех внутренних массивов, а затем для внешнего массива, чтобы получить обещание для массива массивов:
Promise.all(promiseArrArr.map(Promise.all, Promise)).then(arrArr => …)
Обратите внимание, что Promise.all
принимает массив promises, а не массив функций, возвращающих обещание.
Ответ 3
Другим вариантом является сглаживание массива массивов в один массив, который можно использовать непосредственно Promise.all()
. Прямо из примера в MDN, вы можете сделать это, как это, используя .reduce()
и .concat()
:
var promises = [[promise1, promise2], [promise3,promise4], [promise5,promise6]];
Promise.all(promises.reduce(function(a, b) { return a.concat(b); }, []))
.then(function(results) {
// all done here
// results are in a flattened array
});
Это решение позволяет исходному массиву promises содержать либо индивидуальные promises, либо массивы promises или любую комбинацию из двух. Он гибкий таким образом и дает результаты в одном сплющенном массиве результатов, которые находятся в том же порядке, что и исходный promises, но сплющиваются в один массив. Поскольку Promise.all()
требует, чтобы вы передавали ему массив, другие представленные здесь решения требуют, чтобы вход был строгим массивом массивов - этот массив не может иметь простой promises в нем только массивы promises. Это решение является более гибким и будет принимать любой тип ввода.
Например, это будет прекрасно работать, если вход будет таким:
var promises = [promise1, promise2, [promise3, promise4], [promise5, promise6]];
См. рабочую демонстрацию: https://jsfiddle.net/jfriend00/dLsktyyn/
Или вам может показаться полезным использовать функцию flatten()
для других целей:
function flatten(arr) {
return arr.reduce(function(a, b) { return a.concat(b); }, []);
}
var promises = [[promise1, promise2], [promise3,promise4], [promise5,promise6]];
Promise.all(flatten(promises)).then(function(results) {
// all done here
});
Ответ 4
Если у вас есть фиксированное количество подмассивов, я рекомендую использовать это простое решение:
const balancePromises = [...];
const symbolPromises = [...];
const [balances, symbols] = await Promise.all([
Promise.all(balancePromises),
Promise.all(symbolPromises)
]);
Несколько обещаний также можно распараллелить следующим образом:
const [
balances,
debt,
name,
] = await Promise.all([
this.contract.getBalanceOf(user),
this.contract.getDebtOf(user),
this.contract.getNameOf(user),
]);
Ответ 5
Вы можете использовать этот подход:
var promisesArray = [
[promise1, promise2],
[promise3,promise4],
[promise5,promise6]
].reduce(function (arr, item) {
item.forEach(function (promise) {
arr.push(promise);
});
return arr;
}, []);
Promise.all(promisesArray).then(function () {
// code
});