|
Выполнение массива промисов последовательно
Добрый день.
У меня есть промис, который обращается некоторое количество раз к базе данных, производит вычисления и потом при резолве возвращает результат (какую-то структуру). При этом этот промис на входе получает определенную структуру данных из большого массива. Все эти промисы создаются в цикле перебирающем массив входных данных. Сами промисы при создании добавляются в массив. После формирования этого массива я жду 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, время: 18:06. |
|