How to implement Ajax concurrent request control based on JS

How to implement Ajax concurrent request control based on JS

Preface

I recently saw an interview question, of course, it is the title of this article, Ajax concurrent request control, which I think is very interesting. I looked it up in the community and it should be an interview question from ByteDance. Many big guys have summarized this. I have read them all, so I want to try to summarize it myself. The code will be posted at the end of the article. If there is anything wrong, please point it out!

Ajax serial and parallel

  • Serial: Generally, the next interface needs to use the data returned by the previous interface. The commonly used request library for the front end is Axios, which is a Promise-based HTTP library. We can directly use chain calls or Async Await to achieve this, so I won’t demonstrate it.
  • Parallel: multiple requests occur at the same time. Generally, it is used to render the page or perform other operations after all data is obtained. It is mainly based on Promise.all. The implementation method is as follows

The above simulation implements parallel operations based on Promise.all, and the printed results are as follows

Do you feel that this is the end and it doesn’t exist? Now comes the main course. Let's imagine a situation where a page needs to send tens of thousands of requests at the same time, and then perform some operations after all of them succeed. What will be the consequences? The code cannot be executed and the memory overflows. Alas, now we are back to the topic of our article: how to control concurrent Ajax requests? I asked him to output only a certain number of requests at a time until all of them succeeded. Next, I will use two methods to implement this operation. I hope readers will give me some advice.

Two solutions for concurrent request control of Ajax

Promise-based recursion

The following two methods both require the Tasks array in the figure above. Please remember it. The first method based on Promise has the following idea: when you pass in a concurrent pool, a pool of workspaces will be created. Each workspace will go back to get the corresponding task (request) to execute, save it after success, and then continue to get tasks (requests) until there are no tasks in the workspace. Of course, it will terminate directly if it fails. This is the general idea. I have commented on each line of code below. Please accept it.

Class-based implementation

The second method is based on Class. The difference from the above is that this method only creates one workspace. The general idea is: create a workspace to execute tasks (requests), and then push all tasks into it, but each time can only execute the corresponding number of concurrent tasks. When it is less than the number of concurrent tasks, continue to take tasks to execute them until there are no tasks (requests). That's it. The following is the specific implementation.

Code Showcase

Here are the implementation codes of these two methods.

    const delay = function delay(interval) {
      return new Promise((res,rej) => {
        setTimeout(() => {
          res(interval)
        }, interval);
      })
    }


    let tasks = [() => {
      return delay(1000)
    },() => {
      return delay(1003)
    },() => {
      return delay(1005)
    },() => {
      return delay(1002)
    },() => {
      return delay(1004)
    },() => {
      return delay(1006)
    }]

    // Implement parallelism through Promise.all Promise.all(tasks.map(task => task())).then(res => {
      console.log(res);
    })

    // Implement function creatRequest(tasks,pool) based on Promise {
      // The number of requests sent each time is controlled by the pool
      pool = pool || 5
      // Used to store the results of each request (stored in order)
      let results = [],
      // together is used to create workspaces. When pool is passed in, we create several workspaces accordingly. // That is, create an array with the length of pool and the value of null together = new Array(pool).fill(null),
      // index is the task value obtained each time index = 0;
      together = together.map(() => {
        // Management based on Promise return new Promise((resolve,reject) => {
          // Create a function and execute it immediately const run = function run() {
            // If the task pool is empty, it means the request has been sent successfully if(index >= tasks.length) {
              resolve()
              return 
            }
            // First save the index to store the result of the current successful request let old_index = index,
            // Get the currently sent request, and then accumulate the index, so the index will be saved above // ​​Here index++ is calculated first and then accumulated, while ++index is the opposite, first accumulate and then calculate task = tasks[index++];
            // Execute request task().then(result => {
            // Save the successful result results[old_index] = result
            // Recursively continue to execute, that is, continue to get the task to the workspace to execute run();
            }).catch(reason => {
              reject(reason)
            })
          }
          // Execute run() immediately
        })
      })
      // Use Promise.all to control the workspace, that is, make two requests concurrently at a time return Promise.all(together).then(() => results)
    }


    creatRequest(tasks,2).then(results => {
      // All must be successful for the whole to succeed, store the results in order console.log('success',results);
    }).catch(resolve => {
      // If only one of them fails, the whole system will fail console.log('failed');
    })



    // Implement function creatRequest(tasks,pool,callback) based on Class {
      // Parameter restriction and verification if(typeof pool === 'function') {
        callback = pool;
        pool = 5
      }
      if (typeof pool !== 'number') pool = 5
      if (typeof callback !== 'function') callback = function () {}
      //------
      class TaskQueue {
        // Number of running runs = 0;
        // Queue all tasks in queue = [];
        //Store the results of executing tasks (requests) results = [];
        pushTask(task) {
          let self = this
          // Push the task into the workspace self.queue.push(task)
          // Execute the logic of sending the request self.next()
        }
        next() {
          let self = this
          // When the number of tasks being executed is less than the concurrency, continue to take tasks to execute while(self.runing < pool && self.queue.length) {
            self.running++;
            // It is equivalent to taking a task and deleting a task let task = self.queue.shift();
            // Execute request task().then(result => {
              //Save the execution results self.results.push(result)
            }).finally(() => {
              // Clear the number of running items self.runing--
              // Continue executing the request self.next()
            })
          }
          // When there are no tasks, the loop ends if(self.runing === 0) callback(self.results)
        }


      }
      // Instantiation let TQ = new TaskQueue()
      tasks.forEach(task => TQ.pushTask(task))
    }


    creatRequest(tasks,2,results=> {
      console.log(results);
    })

Summarize

The above is a summary of this set of interview questions. I also made a note of it myself. I will continue to update front-end articles in the future. Finally, I hope that all front-end friends can persist in learning and continuously improve their skills. Come on, young man! ! !

This is the end of this article on how to implement Ajax concurrent request control based on JS. For more relevant content on implementing Ajax concurrent request control with JS, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Sample code for using js to implement Ajax concurrent requests to limit the number of requests
  • ByteDance interview: How to use JS to implement Ajax concurrent request control

<<:  Solution to Nginx session loss problem

>>:  Methods and steps to upgrade MySql5.x to MySql8.x

Recommend

How to use docker to build redis master-slave

1. Build a Docker environment 1. Create a Dockerf...

The difference and reasons between the MySQL query conditions not in and in

Write a SQL first SELECT DISTINCT from_id FROM co...

Discussion on CSS style priority and cascading order

In general : [1 important flag] > [4 special fl...

How to achieve seamless token refresh

Table of contents 1. Demand Method 1 Method 2 Met...

Detailed explanation of nginx upstream configuration and function

Configuration Example upstream backend { server b...

HTML implementation of a simple calculator with detailed ideas

Copy code The code is as follows: <!DOCTYPE ht...

Linux uses NetworkManager to randomly generate your MAC address

Nowadays, whether you are on the sofa at home or ...

VMware Workstation 14 Pro installation and activation graphic tutorial

This article shares the installation and activati...

13 JavaScript one-liners that will make you look like an expert

Table of contents 1. Get a random Boolean value (...

Example of converting webpack images to base64

Download url-loader yarn add -D url-loader module...

The difference between absolute path and relative path in web page creation

1. Absolute path First of all, on the local compu...

Graphical explanation of the solutions for front-end processing of small icons

Preface Before starting this article, let’s do a ...