JS实现并发请求数量限制的Demo

2,267 阅读1分钟

起因

想起之前面试被问到过如何实现一个对n多个请求进行并发限制的问题,然后周末就试着实现以下

原理

主要感觉还是把所有请求放到一个数组里面,通过请求有返回之后把他弹出去,然后再压一个请求进来执行。请求请求都是异步的,没办法控制直接控制,只能通过async await 来转成同步。

上代码:

class RequestQueue {  constructor(list, limit) {    this.taskList = list;    this.limit = limit;    this.carryQueue = this.initCarryQueue();  }  initCarryQueue() {    return this.taskList.splice(0, this.limit);  }  async carryAllTasks(callback) {    if (typeof callback !== 'function') {      alert('callback must be a function')      return    }    let result = [];    while (this.carryQueue.length) {        const task = this.carryQueue[0];        try {          const res = await task();          result.push(res)        } catch (error) {          console.log(error)        }        const next = this.taskList.shift();        next && this.carryQueue.push(next);        this.carryQueue.shift()          }    callback(result)  }}

// const p1 = function(){return new Promise(...)}const taskList = [p1, p2, p3, p4, p5, p6]const requestQueue = new RequestQueue(taskList, 3, true);requestQueue.carryAllTasks((res) => {  console.log(res)})

我不会截取动图,效果就是所有请求会排队一个个执行,这样显然是不合理的,因为并非所有请求之间都有因果关系。所以,再改进一下。

改良

class RequestQueue {  constructor(list, limit, isParallel = false) {    this.taskList = list;    this.limit = limit;    this.carryQueue = this.initCarryQueue();    this.isParallel = isParallel  }  initCarryQueue() {    return this.taskList.splice(0, this.limit);  }  async carryAllTasks(callback) {    if (typeof callback !== 'function') {      alert('callback must be a function')      return    }    let result = [];    while (this.carryQueue.length) {      if (this.isParallel) {        // 请求之间无因果关系,并列发起请求        try {          const promiseList = this.carryQueue.map(task => task())          //此处不能用Promise.all,因为Promise.all遇到reject promise.all的状态直接会变成 reject;          const res = await Promise.allSettled(promiseList);          result = result.concat(res);        } catch (error) {          console.log(error)        }        this.carryQueue = this.carryQueue.concat(this.taskList.splice(0, this.limit));        this.carryQueue.splice(0, this.limit);      } else {        // 请求之间有因果关系,排队发起请求        const task = this.carryQueue[0];        try {          const res = await task();          result.push(res)        } catch (error) {          console.log(error)        }        const next = this.taskList.shift();        next && this.carryQueue.push(next);        this.carryQueue.shift()      }    }    callback(result)  }}

改良一下,通过Promise.allSettled 将所有请求执行完毕再统一压进limit 个请求执行。等所有请求完成,通过callback接收最后的执行结果。

最后

虽然文章质量不行,错漏百出,还是希望大佬们看到后可以不吝赐教,拜谢!