1. /*
    2. 题设:JS 实现一个带并发限制的异步调度器 Scheduler,保证同时运行的任务最多有两个
    3. 举例如下:
    4. addTask(1000,"1");
    5. addTask(500,"2");
    6. addTask(300,"3");
    7. addTask(400,"4");
    8. 的输出顺序是:2 3 1 4
    9. 整个的完整执行流程:
    10. 一开始1、2两个任务开始执行
    11. 500ms时,2任务执行完毕,输出2,任务3开始执行
    12. 800ms时,3任务执行完毕,输出3,任务4开始执行
    13. 1000ms时,1任务执行完毕,输出1,此时只剩下4任务在执行
    14. 1200ms时,4任务执行完毕,输出4
    15. */
    16. // 休眠函数
    17. var asleep = time => new Promise((resolve) => {
    18. setTimeout(resolve, time)
    19. })
    20. class Scheduler {
    21. constructor(limit) {
    22. this.maxLimit = limit // 最多同时运行数量
    23. this.runCount = 0 // 当前正在运行任务个数
    24. this.queue = [] // 运行任务队列
    25. }
    26. // 添加任务方法
    27. add(promiseCreator) {
    28. this.queue.push(promiseCreator)
    29. }
    30. // 启动任务入口函数
    31. taskStart() {
    32. for(let i = 0; i < this.maxLimit; i++) {
    33. this.request()
    34. }
    35. }
    36. // 真正调用异步调度方法,自身调用自身,循环执行,直到符合终止条件
    37. request() {
    38. // 终止条件
    39. if(!this.queue || !this.queue.length || this.runCount >= this.maxLimit) {
    40. return
    41. }
    42. // 增加当前运行任务个数
    43. this.runCount++
    44. // console.log('runCount: ', this.runCount)
    45. // 队列头部任务运行
    46. const promiseTask = this.queue.shift()
    47. promiseTask().then(() => {
    48. // 减少当前运行任务个数
    49. this.runCount--
    50. this.request()
    51. })
    52. }
    53. }
    54. // 调用
    55. var scheduler = new Scheduler(2)
    56. var addTask = (time, order) => {
    57. scheduler.add(
    58. () => asleep(time).then(() => {
    59. console.log('order: ', order)
    60. })
    61. )
    62. }
    63. addTask(1000,"1")
    64. addTask(500,"2")
    65. addTask(300,"3")
    66. addTask(400,"4")
    67. // 启动任务
    68. scheduler.taskStart()

    思路:
    1:有个空队列数组 queue;
    2:将所有待执行请求任务塞进 queue 队列中;
    3:调用入口函数 taskStart,并由函数中的 for 循环控制开始时的并发数量;
    4:调用请求函数 request,当有个 request 函数异步完成时,通过监听,在 then 方法中再次调用
    request 方法,从 queue 队列中,取出队头请求任务执行。
    参考:JavaScript 中如何实现并发控制?Promise的并发控制