you_are_enot
@you_are_enot
Пограммист любитель

Как ограничить максимальное количество параллельных запросов?

У меня есть массив, например, из 2000 url на которые нужно отправить запросы, собрать ответы в новый массив и после прохода по всем ссылкам вернуть результат (с помощью Promise.all). При этом нужно, чтобы одновременно выполнялось не более 20 запросов. То есть оправляется первые 20 запросов, как только по одному и них приходит ответ, отправляется следующий.
  • Вопрос задан
  • 114 просмотров
Решения вопроса 1
@Bapen1k
Работает!!!!))
Пришлось писать свой Promise.race, который возвращает индекс решенного промиса в массиве.

В конструктор передается лимит одновременных запросов, который не будет превышать функция. Функция делает сразу N запросов, где N это лимит, как только разрешается один промис делается еще один запрос.

const promiseRace = promises => (
  new Promise((fulfil, reject) => {
    promises.forEach((promise, index) => {
      promise.then(data => fulfil({ data, index }), reject);
    });
  })
);

class Fetcher {
  constructor(maxConnections = 20) {
    this.maxConnections = maxConnections;
  }

  async request(urls, options = {}) {
    const responsePromises = [];

    for (const url of urls) {
      if (responsePromises.length >= this.maxConnections) {
        const { data: response, index } = await promiseRace(responsePromises);
        responsePromises.splice(index, 1);
      }
      responsePromises.push(fetch(url, options));
    }

    return Promise.all(responsePromises);
  }
}

// test
(async () => {
  try {
    const fetcher = new Fetcher(2); // лимит 2
    const urls = [];

    for (let i = 0; i < 200; i++) {
      urls.push(`/api/user/${i}`);
    }

    const responses = await fetcher.request(urls);
    console.log('end');
  } catch (e) {
    console.error(e);
  }
})();
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
inoise
@inoise
Solutions Architect, AWS Certified, Hybrid Cloud
Если скрипт запускается в одном экземпляре то просто каунтер в памяти
Ответ написан
@rPman
Выдавайте новый запрос на каждое следующее подключение на дисконнекте или завершении загрузки (и ошибках) предыдущего, а при запуске всего скрипта поставьте запуск 20 загрузок. Никакой каунтер тогда не понадобится.
Ответ написан
@Azperin
Дилетант
Можно попробовать чтото вроде такого
var originalArr = [...];
var firstArr = originalArr.slice(0, 19);
var restArr = originalArr.slice(19);
firstArr.forEach(fetchNext);

function fetchNext(url) {
	if (!url) {
		return;
	};
	
	fetch(url).then().catch().finaly(() => {
		fetchNext(restArr.shift());
	});
};
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
Сравни.ру Москва
от 150 000 руб.
IWU Нижний Новгород
от 150 000 до 250 000 руб.
Zeus Capital Москва
от 70 000 до 130 000 руб.
24 авг. 2019, в 11:59
5000 руб./за проект
24 авг. 2019, в 11:31
30000 руб./за проект
24 авг. 2019, в 10:59
750 руб./за проект