Skip to content

实现promise并发控制

一般有两种考法:

第一种考法

实现一个类,类有个add函数接收一个promise,类另外有个whenAllDone函数返回一个promise,当所有接收的promise都执行完成时,返回promise状态为fulfilled,并返回promise数组的执行结果。

实现代码展示
js
class PromiseConcurrent {
    constructor(max) {
        this.max = max // 最大并发数
        this.running = 0    // 当前正在运行的promise数量
        this.queue = []      // 等待执行的promise队列
        this.result = []     // 存储每个promise的执行结果
        this.total = 0       // 记录promise的总数量
        this.resolveAll = null  // 所有promise执行完成后的resolve函数
    }
    next() {
        if (this.queue.length === 0 || this.running >= this.max) {
            return
        }
        this.running++
        const {promise, index} = this.queue.shift()
        promise.then((res) => {
            this.result[index] = res
            this.running--
            this.next()
        })
    }
    add(promise) {
        this.queue.push({
            promise, 
            index: this.total
        })
        this.result[index] = null
        this.total++
        if (this.running < this.max) {
            this.next()
        }
    }
    whenAllDone() {
        return new Promise((resolve, reject) => {
            this.resolveAll = resolve
            if (this.queue.length === 0) {
                this.resolveAll(this.result)
            }
        })
    }
}

使用示例:

js
const promiseConcurrent = new PromiseConcurrent(2)
promiseConcurrent.add(Promise.resolve(1))
promiseConcurrent.add(Promise.resolve(2))
promiseConcurrent.add(Promise.resolve(3))
promiseConcurrent.whenAllDone().then((res) => {
    console.log(res) // [1, 2, 3]
})

第二种考法

实现一个类,类有个add函数接收一个promise并返回一个新的promise,新的promise状态与接收的promise状态相同,且返回值为接收的promise的执行结果。

👆这种考的多

实现代码展示
js
class PromiseConcurrent {
    constructor(max) {
        this.max = max // 最大并发数
        this.running = 0    // 当前正在运行的promise数量
        this.queue = []      // 等待执行的promise队列
    }
    next() {
        if (this.queue.length === 0 || this.running >= this.max) {
            return
        }
        this.running++
        const { promise, resolve } = this.queue.shift()
        promise().then((res) => {
            resolve(res)
            this.running--
            this.next()
        })
    }
    add(promise) {
        return new Promise((resolve) => {
            this.queue.push({
                promise,
                resolve,
            })
            if (this.running < this.max) {
                this.next()
            }
        })
    }
}

使用示例:

js
const promiseConcurrent = new PromiseConcurrent(2)
const task = (value, time) => {
    return () => new Promise((resolve) => {
        setTimeout(() => {
            resolve(value)
        }, time * 1000)
    })
}

const task1 = promiseConcurrent.add(task(1, 4))
const task2 = promiseConcurrent.add(task(2, 1))
const task3 = promiseConcurrent.add(task(3, 2))
task1.then((res) => {
    console.log(res)
})
task2.then((res) => {
    console.log(res)
})
task3.then((res) => {
    console.log(res)
})

执行顺序为:task2 -> task3 -> task1

被考过的题:

第一道:

js
const promise1 = () => new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('promise1');
    }, 1000);
});
const promise2 = () => new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('promise2');
    }, 500);
});
const promise3 = () => new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('promise3');
    }, 2000);
});
const promise4 = () => new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('promise4');
    }, 1000);
});
// 正常执行顺序是 promise2 -> promise1 -> promise4 -> promise3  
// 实现一个调度器,最多同时运行max个任务,其他任务等待
const Scheduler = (max) => {
    // 实现代码
}
const scheduler = Scheduler(2);
scheduler(promise1).then((res) => {
    console.log(res);
});
scheduler(promise2).then((res) => {
    console.log(res);
});
scheduler(promise3).then((res) => {
    console.log(res);
});
scheduler(promise4).then((res) => {
    console.log(res);
});