实现一个带并发限制的promise异步调度器

之前看到这个题目,实现一个带并发限制的promise异步调度器,觉得挺有意思,在这里记录一下。

题目是什么意思呢,就是我们正常情况下,promise是没有并发数量限制的,同一个时间可以多个请求同时执行,然后谁返回的速度快,在前端页面直观的就可以打印谁的返回内容。

 1 class Scheduler {
 2   constructor() {}
 3   add(promise) {
 4     this.runTask(promise);
 5   }
 6   runTask(promise) {
 7     promise().then(res => {
 8       console.log(res);
 9     });
10   }
11 }
12 
13 const scheduler = new Scheduler();
14 const timeout = (time, order) => {
15   return new Promise(resolve => {
16     setTimeout(() => {
17       resolve(order);
18     }, time);
19   });
20 };
21 const addTask = (time, order) => {
22   scheduler.add(() => timeout(time, order));
23 };
24 addTask(4000, 1);
25 addTask(1000, 2);
26 addTask(900, 3);
27 addTask(3000, 4);

 

 ok,那我们现在来限制并发数量,假定并发数量最大是2。什么意思呢,就是我们上面例子中,执行任务的盒子,第一个addTask可以放进去,第二个也可以放进去,但第三个不可以立马放进去,因为最大并发数量是2,需要过1000ms,等第二个addTask执行完毕后,那此刻执行任务盒子里只有1个盒子,可以把第三个放进。。。。

那我们来改改 Scheduler。

 1 class Scheduler {
 2   constructor() {
 3     this.max = 2;// 最大限制数
 4     this.work = [];// 正在执行的任务盒子
 5     this.unwork = [];// 等待的任务盒子
 6   }
 7   add(promise) {
 8     if (this.work.length < this.max) {
 9       //还没达到最大数量限制,可以直接执行 
10       this.runTask(promise);
11     } else {
12      // 此时任务盒子数量达到并发最大数量,那就放在等待区域
13       this.unwork.push(promise);
14     }
15   }
16   runTask(promise) {
17     this.work.push(promise);
18     promise()
19       .then(res => {
20         console.log(res);
21       })
22       .finally(() => {
       // 任务执行完毕,就立马从执行任务盒子删掉
23 let index = this.work.indexOf(promise); 24 this.work.splice(index, 1);
// 如果任务等待盒子还有任务,那就继续执行
25 if (this.unwork.length) { 26 this.runTask(this.unwork.shift()); 27 } 28 }); 29 } 30 } 31 32 const scheduler = new Scheduler(); 33 const timeout = (time, order) => { 34 return new Promise(resolve => { 35 setTimeout(() => { 36 resolve(order); 37 }, time); 38 }); 39 }; 40 const addTask = (time, order) => { 41 scheduler.add(() => timeout(time, order)); 42 }; 43 addTask(4000, 1); 44 addTask(1000, 2); 45 addTask(900, 3); 46 addTask(3000, 4); 47

 

 

 我们在打印的内容加个时间,看看每个任务都是过了多久才执行打印出来的。

 1 let date = null;
 2 class Scheduler {
 3   constructor() {
 4     this.max = 2;
 5     this.work = [];
 6     this.unwork = [];
 7   }
 8   add(promise) {
 9     if (this.work.length < this.max) {
10       this.runTask(promise);
11     } else {
12       this.unwork.push(promise);
13     }
14   }
15   runTask(promise) {
16     if (!date) {
17       date = performance.now();
18     }
19     this.work.push(promise);
20     promise()
21       .then(res => {
22         let now = performance.now();
23         let subdate = now - date;
24         /* 处理一下这个时间间隔,因为会多有几十毫秒,处理其他逻辑,如addTask等 */
25         subdate = (subdate / 100).toFixed(0) * 100;
26         console.log('经过多久打印:', subdate, '打印值为:', res);
27       })
28       .finally(() => {
29         let index = this.work.indexOf(promise);
30         this.work.splice(index, 1);
31         if (this.unwork.length) {
32           this.runTask(this.unwork.shift());
33         }
34       });
35   }
36 }
37 
38 const scheduler = new Scheduler();
39 const timeout = (time, order) => {
40   return new Promise(resolve => {
41     setTimeout(() => {
42       resolve(order);
43     }, time);
44   });
45 };
46 const addTask = (time, order) => {
47   scheduler.add(() => timeout(time, order));
48 };
49 addTask(4000, 1);
50 addTask(1000, 2);
51 addTask(900, 3);
52 addTask(3000, 4);

 

 

posted @ 2023-02-06 15:51  蛙仔  阅读(237)  评论(0编辑  收藏  举报