SoFunction
Updated on 2025-03-06

How to control concurrent requests in the front-end gives a detailed explanation

Preface

What situations do front-end control concurrent requests need to be requested multiple times? For example, when the interface returns at one time, there is a lot of data, which causes the browser to render stutter or even crash. At this time, we can issue 6 requests at the same time in batches, so as to avoid lag or crash.

So how does the front-end control concurrent requests?

Key ideas for front-end control of concurrent requests

For example, there are 20 requests, and you need to follow3One group, and the second group is requested after the first group is requested, and so on.

The key idea is to save the request method and request parameters in an array, and then request 3 each time, and then request the next 3 after the request is completed. After each group of requests returns, save the results and wait until all requests are returned, then return all results.

api design

  • pControl: Concurrent request controller, passing the maximum number of concurrency;
  • add: Add requests and parameters;
  • start: Start the request, return to promise, pass after the request is completed.thenGet all results;

Code implementation

function pControl(limit) {
  const taskQueue = [] // {task: Function, params: any[]}[]
  return {
    add,
    start
  }

  function add(task, params) {
    ({
      task,
      params
    })
  }

  function start() {
    return runAllTasks()
  }

  function runAllTasks() {
    const allResults = []
    return new Promise((resolve) => {

      runTask()

      function runTask() {
        if ( === 0) {
          // End of recursion          return resolve(allResults)
        }
        const needRunSize = (, limit)
        const tasks = (0, needRunSize)
        const promises = (({
          task,
          params
        }) => task(params))
        (promises).then((resList) => {
          (...resList)
          // The location of the NOTE recursive call is critical          runTask()
        })
      }
    })
  }
}

Interpretation of key codes

  • pControl: This function returns an object containingaddandstartTwo methods,addUsed to add tasks and parameters,startUsed to start the request, it is a closure.

  • runAllTasks: Return onepromise, and thennew PromiseExecute internally recursivelyrunTask, runTask byExecute concurrent requests,().then()Call againrunTask, realize the return of one set of requests, and then execute the second set of requests.

The key to implementing group waiting is.thenRecursive call in  .

Thinking: Can runAllTasks be implemented using loops?

Yes, need to useasync and for loop + await :

async function runAllTasks2() {
  const allResults = []
  const groupArr = []
  let startIndex = 0
  // Grouping  while (startIndex < ) {
    const arr = (startIndex, startIndex + limit)
    (arr)
    startIndex += limit
  }
  for (let index = 0; index < ; index++) {
    const pList = groupArr[index].map(({
      task,
      params
    }) => task(params))
    const res = await (pList)
    (...res)
  }
  return allResults
}

Cannot be used in loops in for.then, otherwise the next loop will not wait for the previous loop.

usefor ofIterative implementation:

async function runAllTasks2() {
  const allResults = []
  const groupArr = []
  let startIndex = 0
  // Grouping  while (startIndex < ) {
    const arr = (startIndex, startIndex + limit)
    (arr)
    startIndex += limit
  }
  // Iterative grouping  const it = ()
  for (const [key, value] of it) {
    const pList = (({
      task,
      params
    }) => task(params))
    const res = await (pList)
    (...res)
  }
  return allResults
}

How is the combination of loop and promise used?

for 、 while 、 for...ofEqual imperative loop structure, if you want to achieve a waiting effect in the loop, you must useasyncFunction wrapping loopawait, cannot be used.then 。

forEach 、 map 、 filterEqual functional loop structures do not support waiting effects, because these functional loop structures are synchronous and do not support waiting.

asyncandcycle + awaitCombined, achieve the effect of waiting between loops.

andrecursionCombined, achieve the effect of waiting between loops.

Improve the API to make it easier to use

  • Set default parameters:pControlSet an appropriate default value to6, because the same domain name is in, the browser has 6 concurrent requests.
  • start gives callbacks: through callbacks, you can get the request result of each packet and know the current number of requests completed.

These two improvements are simple. Let's see how to use it first:

const asyncTaskControl = pControl() // Default 6(task, params1)
(task, params2)
// ...
(task, params10)

((res, doneSize) => {
  // Get the results of each group of requests and how many requests have been completed  (res) // [{index:number,result:data}] 
  (doneSize)
}).then(allResults => {
  // All request results  (allResults)
})

What is the function of start callback?

It is convenient for users to obtain the results of the current concurrent request and facilitate calculation of completion progress.

Encapsulate the above functions into p-control npm package and release

npm: p-control

Availablenpm i p-controlDownload and use.

summary

  • .thenCombined with recursion, realize waiting between asynchronous tasks;
  • forwhileIs cycle andasync + awaitUse in conjunction to realize waiting between asynchronous tasks;
  • useImplement multiple asynchronous tasks to be executed concurrently.

This is the article about how front-end controls concurrent requests. For more related front-end controls concurrent requests, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!