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 follow3
One 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.then
Get 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 containingadd
andstart
Two methods,add
Used to add tasks and parameters,start
Used to start the request, it is a closure.runAllTasks
: Return onepromise
, and thennew Promise
Execute 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
.then
Recursive 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 of
Iterative 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...of
Equal imperative loop structure, if you want to achieve a waiting effect in the loop, you must useasync
Function wrapping loopawait
, cannot be used.then
。
forEach
、 map
、 filter
Equal functional loop structures do not support waiting effects, because these functional loop structures are synchronous and do not support waiting.
async
andcycle
+await
Combined, achieve the effect of waiting between loops.
and
recursion
Combined, achieve the effect of waiting between loops.
Improve the API to make it easier to use
- Set default parameters:
pControl
Set 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-control
Download and use.
summary
-
.then
Combined with recursion, realize waiting between asynchronous tasks; -
for
、while
Is cycle andasync
+await
Use in conjunction to realize waiting between asynchronous tasks; - use
Implement 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!