控制并发请求数量

93 阅读1分钟

在JavaScript中,我们可以使用一个自定义的并发控制器来限制并发请求的数量。

为了在并发控制中包含失败重试机制,我们可以对每个任务进行封装,确保在失败时重试一定次数。

function limitConcurrencyWithRetry(tasks, limit, retryLimit) {
    const results = [];
    const executing = [];

    function runTask(task, retries) {
        return task().catch(error => {
            if (retries > 0) {
                return runTask(task, retries - 1);
            } else {
                return Promise.reject(error);
            }
        });
    }

    function runTasks() {
        if (tasks.length === 0) return Promise.resolve();

        const task = tasks.shift();
        const p = runTask(task, retryLimit);

        results.push(p);

        const e = p.then(() => executing.splice(executing.indexOf(e), 1));
        executing.push(e);

        let r = Promise.resolve();
        if (executing.length >= limit) {
            r = Promise.race(executing);
        }

        return r.then(() => runTasks());
    }

    return runTasks().then(() => Promise.all(results));
}
// 使用示例
const tasks = Array.from({ length: 1000 }, (_, i) => () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (Math.random() < 0.7) {
                console.log(`Task ${i + 1} done`);
                resolve(i + 1);
            } else {
                console.log(`Task ${i + 1} failed`);
                reject(new Error(`Task ${i + 1} failed`));
            }
        }, Math.random() * 1000);
    });
});

limitConcurrencyWithRetry(tasks, 5, 3).then(results => {
    console.log('All tasks done');
    console.log(results);
}).catch(error => {
    console.error('Some tasks failed', error);
});