Этот вопрос закрыт для ответов, так как повторяет вопрос Как проще всего управлять очередью промисов (не больше N одновременно работающих)?
ProgrammerForever
@ProgrammerForever
Учитель, автоэлектрик, программист, музыкант

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

Добрый день. Есть N операций, которых надо выполнить. Операции можно выполнить асинхронно, поэтому завернул всё в Promise и использую Promise.all. Но есть ограничение: нельзя выполнять больше чем countThreads процессов одновременно (N > countThreads).
Сделал так:
let threadsCount = 10;
let outData = [];
for (let block=0; block*threadsCount<N; block++){
  let allParamsShort = allParams.slice(block*threadsCount, (block+1)*threadsCount);
  
  if (allParamsShort){
    let promises = allParamsShort.map(params=>run(workerFuncName, ...params));
    let data = await Promise.allSettled(promises);
    outData = outData.concat(data);
  };
};

т.е. формирую пачку запросов и выполняю их.
Но один запрос может выполняться 2, а может 50 секунд, и вся пачка простаивает, ожидая последнего.
Подскажите, как можно организовать выполнение, чтобы всегда было запущено countThreads операций, чтобы повысить производительность?
  • Вопрос задан
  • 264 просмотра
Решения вопроса 1
@GrayHorse
Это называется семафором (Semaphore).
class Semaphore {
    constructor(max = 1) {
        if (max < 1) { max = 1; }
        this.max = max;
        this.count = 0;
        this.queue = [];
    }
    acquire() {
        let promise;
        if (this.count < this.max) {
            promise = Promise.resolve();
        } else {
            promise = new Promise(resolve => {
                this.queue.push(resolve);
            });
        }
        this.count++;
        return promise;
    }
    release() {
        if (this.queue.length > 0) {
            const resolve = this.queue.shift();
            resolve();
        }
        this.count--;
    }
}


const semaphore = new Semaphore(10);
for (const url of urls) {
    await semaphore.acquire();
    void downloadUrlSynchronized(url, semaphore);    
}

async function downloadUrlSynchronized(url, semaphore) {
    const resp = await fetch(url);
    const blob = await resp.blob();
    semaphore.release();
    // const name = new URL(url).pathname.slice(1);
    // downloadBlob(blob, name, url);
}

Загрузка (fetch) будет не больше 10 в один момент, что собственно и требовалось.

---
На примере 3:
61ee50a555b4a690601785.png
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Вопрос закрыт для ответов и комментариев

Потому что уже есть похожий вопрос.
Похожие вопросы