What is concurrency?
Because js is single-threaded, front-end concurrency refers to sending multiple data requests in a very short time, such as sending ajax in a loop.
Take a simple example:
The following piece of code is a request for regular mount
stage execution:
useEffect(async () => {
console.time();
await TaskBizService.querySpyTaskSummary();
await TaskBizService.querySpyTask();
console.timeEnd();
// time: 300ms
}, [])
Replace it with this:
useEffect(() => {
console.time();
Promise.all([
TaskBizService.querySpyTaskSummary(),
TaskBizService.querySpyTask(),
]).then((res) => {
console.timeEnd();
});
// time: 120ms
}, [])
It can be seen that there is a lot of room for performance optimization and differences. If multiple requests do not have mutual data dependencies (requirements dependent) during page rendering, directly using parallel requests will speed up the time for data display in the page. The two demos are simultaneously It also involves some knowledge of the event loop.
Therefore, you can also find some optimizable requests in the page and convert them to parallel, which is very helpful for the optimization of the first screen rendering.
Promise.all
Promise.all
Concurrent processing can be used . When promise
all are successful, it will go .then
and get all the values promise
passed in resolve
.
Take a look at this code:
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('request1 end')
}, 1000);
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('request2 end')
}, 3000);
})
console.time(); // 开始计时
Promise.all([p1, p2])
.then(result => {
console.timeEnd(); // default: 3.2s
console.log(result); // (2) ['request1 end', 'request2 end']
})
If Promise.all
any instance fails, the entire concurrency will hang up.
Like this code:
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('request1 end')
}, 1000);
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('request2 fail')
}, 3000);
})
console.time(); // 开始计时
Promise.all([p1, p2])
.then(result => {
// 不会走到这一步
console.timeEnd(); // default: 3.2s
console.log(result);
})
Summarize
-
Promise.all
When dealing with concurrency, if there is apromise
failure, it will not go to .then, but if you only need to execute other side-effect codes after all asynchronous executions are completed, you can write the code in to.finally
implement it. -
But if you need to get the value passed
promise
by the instance after an asynchronous failure , it will not work.resolve
Promise.allSettled
Promise.all
Functions that cannot be realized in , can be realized by using . Promise.allSettled
In Promise.allSettled
, when one of them promise
fails to execute, it will continue to go .then
, and can get the passed resolve、reject
value at the same time. You can use the callback value to judge the request result of the interface to do two things. processing.
The code modification is also very simple, as follows:
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('request1 end')
}, 1000);
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('request2 end')
}, 3000);
})
console.time(); // 开始计时
Promise.allSettled([p1, p2])
.then(result => {
console.timeEnd(); // default: 3.2s
console.log(result); // (2) ['request1 end', 'request2 end']
})
When all the results of the request are complete resolve
, Promise.allSettled
there Promise.all
is not much difference with the request, but catch
a compensation is made for the case.
At the same time Promise.allSettled
, the compatibility did not Promise.all
come well.
Summarize
-
Promise.allSettled
When dealing with concurrency, you are not afraid of asynchronous execution failure, and you will continue to go.then
, which perfectly solvesPromise.all
the situation that you cannot get the value in the case of concurrency failure. -
The only shortcoming is that it is
Promise.all
a little worse than compatibility, and there are two more unsupported browsers, Firefox for Android and Samsung Internet browser.
async/await
async/await
Can it handle concurrency? The answer is yes, but the code will look bloated and difficult to read. Let's take a look at the conventional async/await
asynchronous processing scheme first.
code show as below:
let getData1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('request1 end')
}, 2000);
})
};
let getData2 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('request2 end')
}, 3000);
})
}
let syncFn = async () => {
console.time(); // 开始计时
const data1 = await getData1();
const data2 = await getData2();
console.timeEnd(); // default: 5.8s
console.log(data1, data2); // request1 end, request2 end
}
syncFn();
It can be seen from the time-consuming async/await
that asynchronous blocking is caused, and serial (dependency) requests are actually used, which is also the most common processing method in ordinary projects. Next, let's transform the async/await
parallel request scheme.
let getData1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('request1 end')
}, 2000);
})
};
let getData2 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('request2 end')
}, 3000);
})
}
let syncFn = async () => {
console.time(); // 开始计时
const p1 = getData1();
const p2 = getData2();
const data1 = await p1;
const data2 = await p2;
console.timeEnd(); // default: 3.8s
console.log(data1, data2); // request1 end, request2 end
}
syncFn();
Summarize
-
If it is installed
axios
or other request libraries, in the case that these libraries themselves provide APIs that support concurrency, for exampleaxios.all、axios.spread
, it is recommended to use these APIs provided by them, because as a library with millions of downloads, these APIs provided take into account Boundary conditions and compatibility are definitely better than other native methods. -
In the absence of these libraries, it is recommended to use them
Promise.allSettled
. If you like, you canasync、await
also . There is no difference in the results. It depends on personal preference. But in my opinion, the wayasync、await
of .