Ajax requests under SPA

Since most websites are single-page applications now, there may be dozens or even hundreds of network requests to load a page, but the browser has a limit on the number of concurrent requests, generally 4 to 7 requests, and high concurrent requests will lead to page congestion. Therefore, it is necessary to use Promise based on native JS to develop a system that can control the number of concurrent requests at the same time, allowing multiple concurrent requests for resources without causing the page to freeze.

Based on native JS implementation

Start with code that simulates multiple concurrent requests

const delay = function delay(interval) {
    return new Promise((resolve, reject) = > {
        setTimeout(() = >{ resolve(interval) }, interval); })}let tasks = [
    () = > { return delay(1000)},() = > { return delay(1003)},() = > { return delay(1005)},() = > { return delay(1002)},() = > { return delay(1004)},() = > { return delay(1006)}]Copy the code

The setTimeout asynchronous function is used to simulate multiple concurrent requests. Now, multiple concurrent requests are placed in the array tasks. If the number of concurrent requests is not high, you can directly use promise. all to achieve multiple concurrent requests. There is no solution to the page lag caused by a large number of concurrent tasks, and based on promise.all, an asynchronous task fails and returns a failure message. So we write a function based on native JS to implement the concurrent number of implementations at the same time.

The code implementation is as follows:

function createRequest(tasks, pool) {
    pool = pool || 5;
    let results = [];
    let together = new Array(pool).fill(null);
    let index = 0;
    together = together.map((item, i) = > {
        return new Promise((resolve, reject) = > {
            const run = function run() {
                if (index >= tasks.length) {
                    resolve();
                    return;
                }
                let old_index = index;
                // Get the task from the task pool. Since index is a variable in the upgrade scope, multiple promises share an index
                // This allows tasks in an array to be executed at once
                let task = tasks[index++];
                task().then((result) = > {
                	// Place the returned result in the results box to achieve centralized storage of the requested data.
                    results[old_index] = result;
                    // An asynchronous task is executed only after the previous task is successfully executed
                    run();
                }).catch((reason) = >{ reject(reason) }) } run(); })})// Multiple promises are processed simultaneously, limiting the number of concurrent requests at a time based on the pool
    return Promise.all(together).then(() = > results)
}
Copy the code

CreateRequest splits a set of concurrent requests into different Promise regions based on the pool you pass in, and because it is implemented recursively, the next task in a region will only be executed if the previous one succeeds. The number of concurrent requests at a time is pool, which can solve the problem of page lag caused by instantaneous high concurrency. And the execution results of asynchronous tasks are placed in an array to store centrally, regardless of success or failure, the array is returned, so that you can also use the data returned by the successful execution of asynchronous tasks in the case of failure.

Execution code:

createRequest(tasks, 3).then((results) = > {
    console.log('success->', results);
}).catch((reason) = > {
    console.log('fail->', reason);
})
Copy the code

Result returned:

According to the index value of the map callback function, only three asynchronous tasks are executing at the same time. At this point, concurrent request control for asynchronous tasks is achieved.