preface
Shocksuppression and throttling are two important tools to optimize front-end performance. The core idea is to limit high-frequency behavior.
The difference is:
-
The idea is to respond when the outside world doesn’t change.
-
Throttling is about maintaining your response frequency regardless of how the outside world changes.
Application scenario:
- Anti-shaking: The user hits the submit button crazily. Every time the user clicks the submit button, it will send a request to the server. If it is not restricted, it will consume the server resources meaninglessly. So, we use the idea of anti-shaking, so that when the user stops clicking the button, then we release the request. The shaking proof diagram is as follows:
- Throttling: triggered when the user changes the size of a browser form
resize
Events. The built-inresize
The frequency of event response is too high, which not only does not improve the user experience, but also consumes a lot of resources of the main thread, leading to the lag. Therefore, we would like it to reduce the frequency of the response, so the idea of throttling is a good response to this requirement. The throttling diagram is shown belowscroll
To do an experiment) :
Timer version
Both the shockproof and throttling timers require simple setting and clearing of the timer, first we write the shockproof first.
The anti-shaking code is as follows:
function debounce(fn, delay) {
let timer = null;
return function(. args) {
if(timer) clearTimeout(timer);
timer = setTimeout(function() { fn(... args); },delay) } }Copy the code
On top of that, the throttling only needs to change two lines of code:
function throttle(fn, delay) {
let timer = null;
return function(. args) {
// The first change
if(timer) return;
timer = setTimeout(function(){
// The second change
timer = null; fn(... args); },delay) } }Copy the code
Note: If fn uses this internally, where does this point to? In non-strict mode it is a global object (window in the browser environment). In strict mode, undefined. So, if FN uses this, it might not perform as well as you expected. To do this, we either explicitly bind this with bind, apply, or call, or declare fn in the form of an arrow function to make this point more intuitive.
Use rAF for throttling
RAF, or requestAnimationFrame, will not be analyzed in this article due to space constraints. You can refer to hao God’s article.
Here, we simply regard rAF as a timer whose interval is 16.7ms (of course they are not completely equivalent), and we fix the minimum interval time to about 16.7ms, so as to achieve the effect of N*16.7ms. RAF is much more “punctual” than a regular timer.
Here is just for the purpose of research to broaden the idea, you can understand, I did not go to verify its reliability
function throttle(fn,delay) {
// Estimate the maximum number of counts
let maxCount = delay/(1000/60),
count = 0;
return function(. args) {
requestAnimationFrame(function() {
count++;
if(count > maxCount) { fn(... args); count =0; }}); }}Copy the code
addedThe problem with this code is that there is no guarantee that the last callback will be executed. If you keep triggeringresize
Three seconds, and the interval required for throttling is two seconds, so the expected effect would be two responses around four seconds, but the above code would only respond once, and the last time would be lost. The following GIF illustrates this BUG.
Use rIC for shaking
RIC, aka requestIdleCallback, you can also refer to hao shen’s article.
RIC’s idle callback can be executed at one of two times, either in the interval between each frame or when the user has stopped interacting to spare a time of about 50ms. We can take advantage of the latter in our stabilization.
For the purpose of stabilization, we will respond when the user does not click frequently. So how do you know that the user is no longer doing something? Is through the judge free callback function into IdleDeadline refs. TimeRemaining () value is between 16.7 to 50 ms ms, although it is not reliable.
Note: Here is only for the purpose of research to broaden the idea, you can understand, I did not go to verify its reliability
function debounce(fn) {
let lock = false;
return function(. args) {
// Lock to prevent repeated calls
if (lock) return;
const run = function() {
requestIdleCallback(function(deadline) {
// Print the idle time
console.log(deadline.timeRemaining());
lock = true;
// Judge idle time
if (deadline.timeRemaining() > 1000 / 60) { fn(... args);/ / unlock
lock = false;
} else {
/ / recursionrun(); }}); } run(); }}Copy the code
Let’s demonstrate.
As you can see from the demo diagram, an average of 2 or 3 clicks will trigger a response, which is still a long way from our real business requirements.
Write in the last
In this paper, the common methods to realize the stabilization and throttling are given, and simple experiments are done with rAF and rIC. I suggest you take a look at how LoDash encapsulates and implements shockproof and throttling. For beginners, you can also experience the wonderful use of closures from the implementation of damping and throttling!
About me
Like to chat, like to share, like the cutting-edge 22 side dish chicken, new to the hope to get your attention. Internships/college recruiting opportunities are even better! Personal public account: Rat son’s front end CodeLife