1. Why is function anti-shake and function throttling needed?
- Some calculations and processes are much more expensive than others in the browser. For example,
DOM
Operation over nonDOM
Interactions require more memory and CPU time. Successive attempts to carry on too muchDOM
The operation may cause the browser to hang or even crash.- For example, when resizing a browser,
resize
Events fire consecutively; If theresize
An internal event handler attempt is madeDOM
Operation, whose frequent changes may crash the browser;- To get around the above problem, you need to throttle this class of functions;
2. What are function stabilization and function throttling
Debounce and throttle are similar but different techniques for controlling how many times a function is executed in a given period of time. The basic idea behind this is that some code cannot be executed continuously and repeatedly without interruption.
2.1 Function anti-shake (debounce
)
If an event is triggered more than once frequently and at too short a time interval, the anti-shake function can cause the corresponding event handler to execute only the last time it is triggered. Function stabilization can combine multiple sequential calls into one.
2.2 Function throttling (throttle
)
If an event is frequently fired multiple times, the throttling function can perform the corresponding event handling method at a fixed frequency. Function throttling ensures that an event is executed only once in a given period of time.
3. Application scenarios
type | scenario |
---|---|
Function image stabilization | 1. Mobile phone number and email input detection 2. The search box searches for input (just relax the Ajax request after the last input) 3. Window size resize (Only after the window adjustment is complete, calculate the window size to prevent repeated rendering)4. Rolling events scroll (Handlers that simply execute the last scrolling event that was triggered)5. Verification of text input (Send AJAX request for verification after continuous text input, verify once (after stopping input) |
Function of the throttle | 1. DOM Element drag-and-drop implementation (mousemove )2. Shooters mousedown /keydown Events (only one bullet per unit of time)3. Calculate the distance of mouse movement ( mousemove )4. Search association ( keyup )5. Rolling events scroll , (As long as the page scroll will be judged at an interval of time) |
4. How
4.1 Function anti-shake implementation
function debounce(fn, delay, scope) {
lettimer = null; // The return function forms a closure for the debounce scopereturn function () {
// setThe function environment used in Timeout() is always window, so a copy of the current environment is required;letcontext = scope || this, args = arguments; // If the event is triggered, clear the timer and restart the timer clearTimeout(timer); timer =setTimeout(function() { fn.apply(context, args); }, delay); }}Copy the code
- Code reading
- The first time the function is called, a timer is created that runs the code after a specified interval;
- When the function is called a second time, it clears the previous timer and sets another;
- If the previous timer has already been executed, this operation is meaningless;
- However, if the previous timer is not executed, it is simply replaced with a new timer;
- The goal is to execute only after the request to execute the function has stopped the delay time.
4.2 Function throttling implementation
4.2.1 Simple implementation with timestamp
function throttle(fn, threshold, scope) {
let timer;
let prev = Date.now();
return function () {
let context = scope || this, args = arguments;
let now = Date.now();
if(now - prev > threshold) { prev = now; fn.apply(context, args); }}}Copy the code
4.2.2 Simple implementation using timer
function throttle2(fn, threshold, scope) {
let timer;
return function () {
let context = scope || this, args = arguments;
if(! timer) { timer =setTimeout(function () {
fn.apply(context, args);
timer = null;
}, threshold)
}
}
}
Copy the code
5, for example (scroll
Events)
CSS code
.wrap {
width: 200px;
height: 330px;
margin: 50px;
margin-top: 200px;
position: relative;
float: left;
background-color: yellow;
}
.header{
width: 100%;
height: 30px;
background-color: #a8d4f4;
text-align: center;
line-height: 30px;
}
.container {
background-color: pink;
box-sizing: content-box;
width: 200px;
height: 300px;
overflow: scroll;
position: relative;
}
.content {
width: 140px;
height: 800px;
margin: auto;
background-color: #14ffb2;
}
Copy the code
The HTML code
<div class="wrap">
<div class="header"> scroll events: normal </div> <div class="container">
<div class="content"></div>
</div>
</div>
<div class="wrap">
<div class="header"</strong></div> <div class="container">
<div class="content"></div>
</div>
</div>
<div class="wrap">
<div class="header"</strong></div> <div class="container">
<div class="content"></div>
</div>
</div>
Copy the code
JS code
let els = document.getElementsByClassName('container');
let count1 = 0,count2 = 0,count3 = 0;
const THRESHOLD = 200;
els[0].addEventListener('scroll'.function handle() {
console.log('Normal scrolling event! count1=', ++count1);
});
els[1].addEventListener('scroll', debounce(function handle() {
console.log('Perform the scroll event! Count2 =', ++count2);
}, THRESHOLD));
els[2].addEventListener('scroll', throttle(function handle() {
console.log(Date.now(),', perform the scroll event! (Function throttling) count3=', ++count3);
}, THRESHOLD));
Copy the code
// Function buffetingfunction debounce(fn, delay, scope) {
let timer = null;
let count = 1;
return function () {
let context = scope || this,
args = arguments;
clearTimeout(timer);
console.log(Date.now(), ", trigger", count++, "Second rolling event!");
timer = setTimeout(function () {
fn.apply(context, args);
console.log(Date.now(), The timeout call triggered by the last event can only be executed after the delay time if the high frequency event stops!); }, delay); }}Copy the code
// function throttlingfunction throttle(fn, threshold, scope) {
let timer;
let prev = Date.now();
return function () {
let context = scope || this, args = arguments;
let now = Date.now();
if(now - prev > threshold) { prev = now; fn.apply(context, args); }}}Copy the code
Presentation and comparison of execution results
6. Summary
debounce
andthrottle
Both methods improve the performance of event handlers by reducing the execution of actual event handlers that trigger events at high frequencies, without substantially reducing the number of events that trigger.- Debounce can combine multiple sequential calls into one.
throttle
Ensure that an event is executed only once in a specified period of time.