手写题 - 实现一个带并发限制的异步调度器

2023-12-21 17:35:09

题目

实现一个带并发限制的异步调度器 Scheduler,保证同时运行的任务最多有N个。
完善下面代码中的 Scheduler 类,使得以下程序能正确输出:

class Scheduler {
  add(promiseCreator) { ... }
  // ...
}

const timeout = (time) => new Promise(resolve => {
  setTimeout(resolve, time)
})

const scheduler = new Scheduler(n)
const addTask = (time, order) => {
  scheduler.add(() => timeout(time)).then(() => console.log(order))
}

addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')

// 打印顺序是:2 3 1 4

核心思路:考察 Promise知识点;当任务数超过规定任务数,创建微任务进行等待。

完善代码如下:

class Scheduler {
    constructor(max) {
        this.max = max;
        this.count = 0; // 当前执行中的异步操作
        this.queue = new Array(); // 记录当前的执行数组
    }
    
    async add(promiseCreator) {
        // count >= max 时,此时先不直接执行,将当前异步操作存储起来,当count满足时,再去执行
        // Promise.then的链式调用 new Promise((resolve) => { setTimeout(() => {}, 10000}).then xxxx
        if (this.count >= this.max) {
           /** 这个new Promise单纯只是为了创建个微任务去等,前面加了await,没有resolve()是不会往下走的 */
            await new Promise((resolve, reject) => {
                this.queue.push(resolve);
            });
        }
        
        /** queue某一项resolve()后会从这儿往下走  */
        this.count++;
        let res = await promiseCreator();// 执行timeout(time)
        this.count--; // 执行完1轮才往下走到这儿
        
        if (this.queue.length) {
            this.queue.shift()();//删除queue数组第一项并执行resolve()
        }
        
        return res;
    }
}
    
const timeout = (time) => new Promise(resolve => {
  setTimeout(resolve, time)
})

const scheduler = new Scheduler(n) // 任务2=>n即为2
const addTask = (time, order) => {
  scheduler.add(() => timeout(time)).then(() => console.log(order))
}

addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4') 

运行结果如下:

在这里插入图片描述

其他
打印测试:

class Scheduler {
  constructor(max) {
    this.max = max
    this.count = 0 // 当前执行中的异步操作
    this.queue = new Array() // 记录当前的执行数组
  }

  async add(promiseCreator) {
    // count >= max 时,此时先不直接执行,将当前异步操作存储起来,当count满足时,再去执行
    // Promise.then的链式调用 new Promise((resolve) => { setTimeout(() => {}, 10000}).then xxxx
    if (this.count >= this.max) {
      await new Promise((resolve, reject) => {
        this.queue.push(resolve)
      })
    }
    this.count++
    const res = await promiseCreator()
    this.count--

    if (this.queue.length) {
      this.queue.shift()()
    }
    console.log('res: ', res)

    return res
  }
}
const timeout = (time) => new Promise(resolve => {
  console.log('100')
  setTimeout(resolve, time)
})

const scheduler = new Scheduler(2)
const addTask = (time, order) => {
  scheduler.add(() => timeout(time)).then(() => {console.log(order); return 'timeout'})
}

addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')

打印结果:
100
100
res: undefined
100
2
res: undefined
100
3
res: undefined
1
res: undefined
4
// 解释:
// ∵setTimeout(resolve, time) resolve后面木有具体值,∴res: undefined
// ∵this.queue.shift()()即resolve()是同步代码,∴先打印下一个’100’再return res打印’2’
在这里插入图片描述

文章来源:https://blog.csdn.net/Xxxxxl17/article/details/135126808
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。