Promise之异步并发控制

373 阅读3分钟

实现一个批量请求函数 multiRequest(urls, maxNum),要求如下:

  • 要求最大并发数 maxNum
  • 每当有一个请求返回,就留下一个空位,可以增加新的请求
  • 所有请求完成后,结果按照 urls 里面的顺序依次打出
// 用于测试生成promise
let p = function (t) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (Math.random() > 0.5) {
                resolve(t)
            } else {
                reject(t)
            }
        }, 1000)
    })
}

function multiRequest(urls, maxNum) {
    let len = urls.length, 
        count = 0; // promise计数
    let result = new Array(len); // 请求结果
    return new Promise((resolve, reject) => {
        // while循环并发请求,数量小于maxNum
        while (count < maxNum) {
            next()
        }
        function next() {
            let current = count++;
            // 边界判断,result中不包含空值empty
            // 关于边界判断,需要判断result中都是resolve或者reject的结果,不然就会产生空值
            if (current >= len) {
                !result.includes()&&resolve(result);
                return
            }
            let promise = p(urls[current]);
            promise.then(res => {
                console.log('成功', res, Date.now())
                result[current] = res;
                // 递归next
                if (current < len) next()
            }).catch(err => {
                console.log('失败', err, Date.now())
                result[current] = err;
                if (current < len) next()
            })
        }
    })
}

测试结果如下:

multiRequest([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 2).then(res => {
    console.log(res)
})
// 输出结果
// 失败 1 1649262788371
// 成功 2 1649262788375
// 失败 3 1649262789391
// 成功 4 1649262789391
// 成功 5 1649262790405
// 成功 6 1649262790405
// 失败 7 1649262791415
// 失败 8 1649262791415
// 失败 9 1649262792425
// 成功 10 1649262792426
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

multiRequest([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3).then(res => {
    console.log(res)
})
// 输出结果
// 成功 1 1649262865399
// 成功 2 1649262865403
// 失败 3 1649262865404
// 成功 4 1649262866409
// 失败 5 1649262866409
// 失败 6 1649262866409
// 成功 7 1649262867418
// 成功 8 1649262867418
// 成功 9 1649262867418
// 成功 10 1649262868433
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

题目二,具体要求如下:

//支持并发的调度器, 最多允许2两任务进行处理 
const scheduler = new Scheduler(2) 
scheduler.addTask(1, '1'); // 1s后输出'1' 
scheduler.addTask(2, '2'); // 2s后输出'2' 
scheduler.addTask(1, '3'); // 2s后输出'3' 
scheduler.addTask(1, '4'); // 3s后输出'4' 
scheduler.start();

这里可以使用与上面类似方式来实现

class Scheduler{
    constructor(n){
        this.maxNum = n;
        this.tasks = []
    }

    addTask(delay, data){
        let task = () => {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(data)
                }, delay * 1000)
            })
        }
        this.tasks.push(task)
    }

    start(){
        let self = this;
        console.log(Date.now())
        let i = 0;
        while(i < this.maxNum){
            next();
        }
        function next(){
            let current = i++
            if(current >= self.tasks.length) return
            let task = self.tasks[current];
            task().then(res => {
                console.log(res, Date.now())
                if (current < self.maxNum) next()
            })
        }
    }
}

const scheduler = new Scheduler(2)
scheduler.addTask(1, '1'); 
scheduler.addTask(2, '2');
scheduler.addTask(1, '3');
scheduler.addTask(1, '4');
scheduler.start();
// 1649430094783
// 1 1649430095790
// 2 1649430096797
// 3 1649430096797
// 4 1649430097803

以上全部内容,如有疑问,欢迎指正。Good Luck!

56.webp