Limiting AXIOS concurrent requests (TypeScript)

In a scenario where a user needs to upload 1000 images at the same time, each image requires a separate POST request. However, the browser or server has a limit on the number of concurrent requests. If the number of concurrent requests exceeds the limit, an error may be reported. Therefore, you need to limit the number of concurrent front-end requests.

This encapsulates the asynchronous task as a Promise.

/ * *@format * /

/** * Encapsulates the number of axiOS concurrent requests */
export default class LimitPromise {
  private _max: number;
  private _count: number;
  private _taskQueue: any[];

  constructor(max: number) {
    // The maximum concurrency of asynchronous tasks
    this._max = max || 6;
    // Number of tasks currently being executed
    this._count = 0;
    // Queue of tasks waiting to be executed
    this._taskQueue = [];
  }

  /** * the asynchronous task function and its arguments are passed to *@param Caller asynchronous task function, which must be an async function or return a Promise function *@param Args Parameter list of asynchronous task function *@returns {Promise<unknown>} Return a Promise */
  call(caller: (... arg:any[]) = >any) {
    return new Promise((resolve, reject) = > {
      const task = this._createTask(caller, resolve, reject);
      if (this._count >= this._max) {
        this._taskQueue.push(task);
      } else{ task(); }}); }/** * Create a task *@param Caller The actual function executed *@param Args executes arguments to the function *@param resolve
   * @param reject
   * @returns {Function} Returns a task function *@private* /
  _createTask(caller: (... arg:any[]) = >any,
    resolve: (value: any | PromiseLike<any= > >)void, reject: (reason? :any) = >void
  ) {
    return () = > {
      This is where the asynchronous task is actually called and the return of the asynchronous task (resolve and reject) is thrown up to the upper level
      caller()
        .then(resolve)
        .catch(reject)
        .finally(() = > {
          // The consumption area of the task queue, using the Promise finally method, takes out the next task to execute after the asynchronous task ends
          this._count--;
          if (this._taskQueue.length) {
            const task = this._taskQueue.shift(); task(); }});this._count++; }; }}Copy the code

Use the enclosed LimitPromise class to wrap the POST method in the AXIos configuration file:

import LimitPromise from './limitReq';
import axios, { AxiosRequestConfig } from 'axios';

const limtReq = new LimitPromise(6);
export const limitPost = (
  url: string, data? :any, config? : AxiosRequestConfig, resolve? : (value:any | PromiseLike<any= > >)void, reject? : (reason? :any) = >void
) = >
  limtReq
    .call(() = > axios.post(url, data, config))
    .then(resolve)
    .catch(reject);
Copy the code

(Other methods such as get, PUT, etc., can be wrapped as above.) Then simply change the original axios.post request to limitPost.