Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 30.06.2018, 17:30
Интересующийся
Отправить личное сообщение для arealhz Посмотреть профиль Найти все сообщения от arealhz
 
Регистрация: 21.01.2017
Сообщений: 11

Выполнение массива промисов последовательно
Добрый день.
У меня есть промис, который обращается некоторое количество раз к базе данных, производит вычисления и потом при резолве возвращает результат (какую-то структуру). При этом этот промис на входе получает определенную структуру данных из большого массива. Все эти промисы создаются в цикле перебирающем массив входных данных. Сами промисы при создании добавляются в массив. После формирования этого массива я жду Promise.all() и получаю массив результатов. Всё бы хорошо. Но вычисления в зависимости от результатов запросов внутри промиса могут быть разные по протяженности, а количество одновременных подключений к базе данных для решения этих промисов ограниченно. И все прекрасно работает, когда в массиве исходных данных 10-20 элементов. А когда там около 500-1000 элементов, то где-то в середине количество одновременных подключений уже вырастает до недопустимого, и база данных перестаёт быть доступной для большей половины промисов. При этом Promise.all уже не выполняется успешно, так как вылазят ошибки в дочерних промисах.

Теперь внимаение впорос

Как можно выполнить массив промисов ПОСЛЕДОВАТЕЛЬНО, то есть что бы элемент n выполнялся строго после завершения выполнения элемента n-1?

P.S.: Так же интересны варианты выполнения массивов промисов секторно, на пример по 10шт за раз (что бы эффективно использовать пул подключений к базе данных на пример)
Ответить с цитированием
  #2 (permalink)  
Старый 30.06.2018, 19:28
Аватар для destus
Профессор
Отправить личное сообщение для destus Посмотреть профиль Найти все сообщения от destus
 
Регистрация: 18.05.2011
Сообщений: 1,207

Обычный цикл for с использованием внутри себя await. Если нужно несколько промисов за раз, то соответственно увеличение переменной-счетчик на нужное значение и Promise.all() в теле цикла.
Ответить с цитированием
  #3 (permalink)  
Старый 30.06.2018, 19:38
Аватар для Белый шум
Профессор
Отправить личное сообщение для Белый шум Посмотреть профиль Найти все сообщения от Белый шум
 
Регистрация: 19.01.2012
Сообщений: 498

По-моему вам нужна обёртка над запросами к БД, которая бы следила за числом подключений к базе.
Ответить с цитированием
  #4 (permalink)  
Старый 30.06.2018, 20:20
Интересующийся
Отправить личное сообщение для arealhz Посмотреть профиль Найти все сообщения от arealhz
 
Регистрация: 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?
Ответить с цитированием
  #5 (permalink)  
Старый 30.06.2018, 20:23
Интересующийся
Отправить личное сообщение для arealhz Посмотреть профиль Найти все сообщения от arealhz
 
Регистрация: 21.01.2017
Сообщений: 11

Сообщение от Белый шум Посмотреть сообщение
По-моему вам нужна обёртка над запросами к БД, которая бы следила за числом подключений к базе.
Я "сильно новичок" у меня не тот уровень, что бы писать воркароунд для баз данных. Я постигаю асинхронную модель программирования после долгих лет работы с последовательным выполнением кода. И писал всегда утилиты для администрирования, так как я не программист, а админ
Ответить с цитированием
  #6 (permalink)  
Старый 30.06.2018, 20:30
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,511

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.
Ответить с цитированием
  #7 (permalink)  
Старый 30.06.2018, 21:04
Интересующийся
Отправить личное сообщение для arealhz Посмотреть профиль Найти все сообщения от arealhz
 
Регистрация: 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...
Ответить с цитированием
  #8 (permalink)  
Старый 30.06.2018, 21:46
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,511

Чтоб в этом разбираться, надо просто понимать, что async и await - это не что-то самостоятельное, а просто удобная обёртка над Promise. Promise же в свою очередь - это не что-то самостоятельное, а просто удобная обёртка над коллбэками.)
Поняв коллбэки поймёшь и остальное.)
__________________
29375, 35
Ответить с цитированием
  #9 (permalink)  
Старый 01.07.2018, 00:45
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,007

Сообщение от arealhz Посмотреть сообщение
P.S.: Так же интересны варианты выполнения массивов промисов секторно, на пример по 10шт за раз (что бы эффективно использовать пул подключений к базе данных на пример)
Самый правильный вариант - "общая очередь". Запускаются параллельно 10 исполнителей, каждый из которых последовательно забирает и обрабатывает элементы из очереди и резолвится, если очередь опустела. А внешний Promise.all ждёт всех десятерых.

Главный плюс - если какой-то пункт обрабатывается долго, он не тормозит остальных.
Ответить с цитированием
  #10 (permalink)  
Старый 01.07.2018, 04:52
Профессор
Отправить личное сообщение для Audaxviator Посмотреть профиль Найти все сообщения от Audaxviator
 
Регистрация: 28.04.2017
Сообщений: 214

Посмотрите старую добрую библиотеку async, там 100500 методов на все вкусы и случаи жизни.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Соединение массива Artur_Hopf Общие вопросы Javascript 4 07.06.2018 16:48
Обход многомерного массива с задержкой после каждого цикла Walk Общие вопросы Javascript 2 14.08.2017 16:17
Вывод последовательно итераций массива без перезагрузки lexus777 AJAX и COMET 1 28.03.2016 14:31
Помогите к js коду, написать html код Modrih Элементы интерфейса 8 16.06.2015 18:08
Сортировка массива по возрастанию другого массива. vas88811 Events/DOM/Window 4 12.01.2014 10:31