30.06.2018, 17:30
|
Интересующийся
|
|
Регистрация: 21.01.2017
Сообщений: 11
|
|
Выполнение массива промисов последовательно
Добрый день.
У меня есть промис, который обращается некоторое количество раз к базе данных, производит вычисления и потом при резолве возвращает результат (какую-то структуру). При этом этот промис на входе получает определенную структуру данных из большого массива. Все эти промисы создаются в цикле перебирающем массив входных данных. Сами промисы при создании добавляются в массив. После формирования этого массива я жду Promise.all() и получаю массив результатов. Всё бы хорошо. Но вычисления в зависимости от результатов запросов внутри промиса могут быть разные по протяженности, а количество одновременных подключений к базе данных для решения этих промисов ограниченно. И все прекрасно работает, когда в массиве исходных данных 10-20 элементов. А когда там около 500-1000 элементов, то где-то в середине количество одновременных подключений уже вырастает до недопустимого, и база данных перестаёт быть доступной для большей половины промисов. При этом Promise.all уже не выполняется успешно, так как вылазят ошибки в дочерних промисах.
Теперь внимаение впорос
Как можно выполнить массив промисов ПОСЛЕДОВАТЕЛЬНО, то есть что бы элемент n выполнялся строго после завершения выполнения элемента n-1?
P.S.: Так же интересны варианты выполнения массивов промисов секторно, на пример по 10шт за раз (что бы эффективно использовать пул подключений к базе данных на пример)
|
|
30.06.2018, 19:28
|
|
Профессор
|
|
Регистрация: 18.05.2011
Сообщений: 1,207
|
|
Обычный цикл for с использованием внутри себя await. Если нужно несколько промисов за раз, то соответственно увеличение переменной-счетчик на нужное значение и Promise.all() в теле цикла.
|
|
30.06.2018, 19:38
|
|
Профессор
|
|
Регистрация: 19.01.2012
Сообщений: 505
|
|
По-моему вам нужна обёртка над запросами к БД, которая бы следила за числом подключений к базе.
|
|
30.06.2018, 20:20
|
Интересующийся
|
|
Регистрация: 21.01.2017
Сообщений: 11
|
|
Я пробовал вот такую модель:
"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?
|
|
30.06.2018, 20:23
|
Интересующийся
|
|
Регистрация: 21.01.2017
Сообщений: 11
|
|
Сообщение от Белый шум
|
По-моему вам нужна обёртка над запросами к БД, которая бы следила за числом подключений к базе.
|
Я "сильно новичок" у меня не тот уровень, что бы писать воркароунд для баз данных. Я постигаю асинхронную модель программирования после долгих лет работы с последовательным выполнением кода. И писал всегда утилиты для администрирования, так как я не программист, а админ
|
|
30.06.2018, 20:30
|
|
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,587
|
|
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)
}
}())
__________________
29375, 35
Последний раз редактировалось Aetae, 30.06.2018 в 20:46.
|
|
30.06.2018, 21:04
|
Интересующийся
|
|
Регистрация: 21.01.2017
Сообщений: 11
|
|
Сообщение от Aetae
|
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...
|
|
30.06.2018, 21:46
|
|
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,587
|
|
Чтоб в этом разбираться, надо просто понимать, что async и await - это не что-то самостоятельное, а просто удобная обёртка над Promise. Promise же в свою очередь - это не что-то самостоятельное, а просто удобная обёртка над коллбэками.)
Поняв коллбэки поймёшь и остальное.)
__________________
29375, 35
|
|
01.07.2018, 00:45
|
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 1,012
|
|
Сообщение от arealhz
|
P.S.: Так же интересны варианты выполнения массивов промисов секторно, на пример по 10шт за раз (что бы эффективно использовать пул подключений к базе данных на пример)
|
Самый правильный вариант - "общая очередь". Запускаются параллельно 10 исполнителей, каждый из которых последовательно забирает и обрабатывает элементы из очереди и резолвится, если очередь опустела. А внешний Promise.all ждёт всех десятерых.
Главный плюс - если какой-то пункт обрабатывается долго, он не тормозит остальных.
|
|
01.07.2018, 04:52
|
Профессор
|
|
Регистрация: 28.04.2017
Сообщений: 214
|
|
Посмотрите старую добрую библиотеку async, там 100500 методов на все вкусы и случаи жизни.
|
|
|
|