как использовать обещания bluebirdJS для выполнения запросов API в ПАКЕТАХ вместо простого ограничения параллелизмом

У меня есть 1000 запросов HTTP API, которые нужно сделать. Я сдержал их все как обещания в массиве. Я хочу выполнять их «ПАКЕТАМИ» из 100 за раз - не более того, чтобы избежать ограничения скорости / дросселирования API и т. Д.

Хотя bluebirdJS предоставляет функцию .map() с параметром concurrency, он ограничивает количество звонков, сделанных ЗА ВРЕМЯ. Это означает, что одновременно обрабатывается не более 100 одновременных запросов - как только первый запрос будет разрешен, он начнет обрабатывать 101-й запрос - он не ждет, пока все 100 разрешатся, прежде чем начинать с следующие 100.

Я ищу поведение "BATCHING" - сначала обработать 100 запросов, а ТОЛЬКО ПОСЛЕ всех 100 запросов выполнены, он должен начаться со следующих 100 запросов.

Предоставляет ли BlueBirdJS какой-либо API из коробки для обработки пакетов таким образом?


person Rakib    schedule 31.08.2017    source источник
comment
Разве нельзя разбить запрос на список из 100 элементов каждый и применить Promise.all внутри Promise.each do?   -  person Prasanna    schedule 31.08.2017


Ответы (1)


Вы можете разбить большой массив urls на массив партий. Для каждого пакета запускайте Promise#map, который будет разрешен, когда все операции async будут завершены. И запускайте эти пакеты последовательно, используя Array#reduce.

let readBatch(urls) {
  return Promise.map(url => request(url));
}

let read(urlBatches) {
  return urlBatches.reduce((p, urls) => {
    return p.then(() => readBatch(urls));
  }, Promise.resolve());
}

const BATCH_SIZE = 100;
let urlBatches = [];
for (let i = 0; i < urls.length; i+= BATCH_SIZE) {
  let batch = array.slice(i, i + BATCH_SIZE);
  urlBatches.push(batch);
}

read(urlBatches)
   .then(() => { ... }) // will be called when all 1000 urls are processed
person alexmac    schedule 31.08.2017
comment
хорошо .... я использовал .mapSeries() вместо .reduce для последовательного выполнения пакетов .... код несколько чище с .mapSeries() - person Rakib; 06.09.2017
comment
В вашем вопросе, который вы задали о решении для запуска нового пакета, ТОЛЬКО ПОСЛЕ того, как все 100 запросов будут выполнены Bluebird#mapSeries работает по-другому. Он выполняет операции последовательно, а не параллельно docs. - person alexmac; 06.09.2017
comment
Но это то, что мы пытаемся сделать, верно? Чтобы запускать одну партию за другой серией / последовательностью - так Bluebird#mapSeries() делает именно то, что вы цитировали в документации. Однако обещания ВНУТРИ партии могут выполняться параллельно. - person Rakib; 07.09.2017
comment
Нет, это другое. Array#reduce запускает пакеты последовательно, но асинхронные операции в пакете выполняются параллельно. _2 _... Я не понимаю, как его можно использовать для запуска пакетов, он может запускать только асинхронные операции в пакете и только последовательно. - person alexmac; 07.09.2017