|
Выполнение массива промисов последовательно
Добрый день.
У меня есть промис, который обращается некоторое количество раз к базе данных, производит вычисления и потом при резолве возвращает результат (какую-то структуру). При этом этот промис на входе получает определенную структуру данных из большого массива. Все эти промисы создаются в цикле перебирающем массив входных данных. Сами промисы при создании добавляются в массив. После формирования этого массива я жду Promise.all() и получаю массив результатов. Всё бы хорошо. Но вычисления в зависимости от результатов запросов внутри промиса могут быть разные по протяженности, а количество одновременных подключений к базе данных для решения этих промисов ограниченно. И все прекрасно работает, когда в массиве исходных данных 10-20 элементов. А когда там около 500-1000 элементов, то где-то в середине количество одновременных подключений уже вырастает до недопустимого, и база данных перестаёт быть доступной для большей половины промисов. При этом Promise.all уже не выполняется успешно, так как вылазят ошибки в дочерних промисах. Теперь внимаение впорос :) Как можно выполнить массив промисов ПОСЛЕДОВАТЕЛЬНО, то есть что бы элемент n выполнялся строго после завершения выполнения элемента n-1? P.S.: Так же интересны варианты выполнения массивов промисов секторно, на пример по 10шт за раз (что бы эффективно использовать пул подключений к базе данных на пример) |
Обычный цикл for с использованием внутри себя await. Если нужно несколько промисов за раз, то соответственно увеличение переменной-счетчик на нужное значение и Promise.all() в теле цикла.
|
По-моему вам нужна обёртка над запросами к БД, которая бы следила за числом подключений к базе.
|
Я пробовал вот такую модель:
"use strict";
'esversion: 6';
async function procData(val, i){
await setTimeout(() => {
var ret = i + "\t" + val + " #";
console.log(ret);
}, 3000);
// return ret;
}
var arr = [3, 5, "asdf", 8, 0];
//arr.forEach(procData(val,i));
//let i = -5;
for(let n in arr){
procData(arr[n],n)
// i++;
}
Я понимаю, что здесь я дожидаюсь исполнения конкретного запроса в промисе, но как это ожидание переместить внутрь цикла формирования промисов не совсем понятно. ( Но ничего не вышло. После долгих лет PERL трудно перейти на асинхронную модель программирования. :( Может я не правильно реализовал async/await? |
Цитата:
|
1. setTimeout - не возвращает промис, его бесполезно await.
2. ключевое слово await имеет смысл использовать именно там, где ты что-то ждёшь.(а конкретно исключительно перед промисом или вызовом async функции) Если async функция вызвана без этого ключевого слова - то она просто вызвана, дальнейший код не ждёт асинхронного ответа, независимо от того, что там у ней внутри. Примерно так должен был выглядеть код:
"use strict";
'esversion: 6';
(async function(){
function procData(val, i){
return new Promise((resolve, reject) => setTimeout(() => {
var ret = i + "\t" + val + " #";
console.log(ret);
resolve(ret)
}, 3000));
}
var arr = [3, 5, "asdf", 8, 0];
for(let n in arr){
await procData(arr[n],n)
}
}())
|
Цитата:
Сейчас буду пытаться разобрать этот код, так как без понимания что происходит - использовать вряд ли получиться. Спасибо большое за пример работающей конструкции! Буду теперь RTFM... |
Чтоб в этом разбираться, надо просто понимать, что async и await - это не что-то самостоятельное, а просто удобная обёртка над Promise. Promise же в свою очередь - это не что-то самостоятельное, а просто удобная обёртка над коллбэками.)
Поняв коллбэки поймёшь и остальное.) |
Цитата:
Главный плюс - если какой-то пункт обрабатывается долго, он не тормозит остальных. |
Посмотрите старую добрую библиотеку async, там 100500 методов на все вкусы и случаи жизни.
|
| Часовой пояс GMT +3, время: 23:25. |
|