js 的异步并发控制

395 阅读1分钟

问题描述:

实际场景:大文件断点续传

一次性发10个请求,但是并发量很大,想一次只发2个请求,某一个请求完了,就让第3个补上,又请求完了,让第4个补上,以此类推,让最高并发量变成可控的。

目前找到的三种解决方案

sindresorhus(大佬)

image.png

1.p-limit

github.com/sindresorhu… 使用:

 npm install p-limit
import pLimit from 'p-limit';

const limit = pLimit(1);

const input = [
	limit(() => fetchSomething('foo')),
	limit(() => fetchSomething('bar')),
	limit(() => doSomething())
];

// Only one promise is run at once
const result = await Promise.all(input);
console.log(result);

2.async-pool

使用:

 import asyncPool from 'tiny-async-pool'
 const timeout = (i) => new Promise((resolve) => setTimeout(() => resolve(i), i))
 const results = await asyncPool(2, [1000, 5000, 3000, 2000], timeout)

3.感谢林三心大佬的文章分享

juejin.cn/post/703339…

class Scheduler {
    constructor(limit) {
        this.queue = []
        this.limit = limit
        this.count = 0
    }


    add(time, order) {
        const promiseCreator = () => {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log(order)
                    resolve()
                }, time)
            })
        }
        this.queue.push(promiseCreator)
    }

    taskStart() {
        for (let i = 0; i < this.limit; i++) {
            this.request()
        }
    }

    request() {
        if (!this.queue.length || this.count >= this.limit) return
        this.count++
        this.queue.shift()().then(() => {
            this.count--
            this.request()
        })
    }
}

使用:

// 测试
const scheduler = new Scheduler(3);
const addTask = (time, order) => {
        scheduler.add(time, order);
};
addTask(1000, "1");
addTask(1000, "2");
addTask(1500, "3");
addTask(1000, "4");
scheduler.taskStart();

完!