preface
Front-end development will encounter some frequent events triggered, such as: Window scroll, resize; Mousedown, Mousemove, KeyUp, keyDown, etc., if you do not do anything to your code, you will find that the page is stuck, trigger interface requests frequently and other problems, this article will analyze the function throttling and anti-shaking implementation, step by step gradually reveal the function throttling and anti-shaking true 💜
concept
Understand the principle of anti-shake and throttling trigger, and use them properly according to different application scenarios
Function debounce
If the action is invoked within n milliseconds, the execution time is recalculated and the action is not executedCopy the code
Understanding principle: although trigger event, but must be in the event triggered n seconds after the execution, if an event triggered within n seconds and triggered the event, with the time of the new event shall prevail, n seconds after the execution, in short, is to trigger the event within n seconds no longer triggered event, will be executed!
Function throttle
A predetermined execution period is set to execute the action at a time greater than or equal to the execution period, and then the next new periodCopy the code
Understanding principle: within a specified time, ensure the execution of this function
implementation
Image stabilization
According to the principle of anti-shake, the implementation code is as follows, and the following examples will be used in general:
# arrow log function
let count = 0
const log = () => {
console.log(this)
++count
console.log(count)
}
# function expression
const log = function (evt) {
console.log(this)
console.log(evt)
++count
console.log(count)
}
Copy the code
const debounce = function (fn, delay){
let timeout = null
return function () {
if (timeout) {
clearTimeout(timeout)
}
timeout = setTimeout(fn, delay)
}
}
Copy the code
Onclick = debounce(log, 1000) React Demo:… onClick={debounce(log.bind(this), 1000)}
Have you found that there are still defects in the anti-shake function at this time
- This points to and event objects
- If the user keeps clicking the submit button now, the request will never be sent and will not be prompted, which is pretty bad for the user experience
This points to and event objects
This points to the
- In the log function console.log(this), the value of this is undefined when debounce is not used. This is because the arrow function is used and bind(this) is called when onClick is called. This points to the react component example
- In conventional use console.log(this), when debounce is not used, the value of this is:
<div id="mecontain"></div>
The event object
- Without the debouce function, the ClickEvent object is printed
- The debounce function, however, prints only undefined
Solve the above problems to change our code
const debounce = function (fn, delay){
let timeout = null
return function () {
const context = this;
const args = arguments;
clearTimeout(timeout)
timeout = setTimeout(() => {
fn.apply(context, args)
}, delay)
}
}
Copy the code
Interactive optimization experience
If you want to execute the function immediately, do not wait until the event stops triggering. After the event stops triggering for n seconds, you can trigger the function again by adding isImmeDiate to check whether the function is executed immediately
const debounce = function (fn, delay,isImmeDiate= false) {let timeout = null
return function () {
const context = this;
const args = arguments;
if(timeout) clearTimeout(timeout)
if(isImmeDiate) {
# Check if it has already been executed, do not repeat execution
letcallNow = ! timeout timeout =setTimeout(function(){
timeout = null;
}, delay)
if(callNow) result = fn.apply(context, args)
} else {
timeout = setTimeout(() => {
fn.apply(context, args)
}, delay)
}
return result
}
}
Copy the code
To add a cancel debounce switch, simply add a cancle function to clear timer timeout = null
const debounce = function (fn, delay,isImmeDiate= false) {let timeout = null
const debounced = function () {
const context = this;
const args = arguments;
if(timeout) clearTimeout(timeout)
if(isImmeDiate) {
# Check if it has already been executed, do not repeat execution
# setTimeout is also constantly updated
letcallNow = ! timeout timeout =setTimeout(function(){
timeout = null;
}, delay)
if(callNow) result = fn.apply(context, args)
} else {
timeout = setTimeout(() => {
fn.apply(context, args)
}, delay)
}
return result
}
debounced.prototype.cancle = function() {
clearTimeout(timeout)
timeout = null
}
return debounced
}
Copy the code
So far we have implemented an anti-shake function, but do you have any other ideas?
The throttle
According to the principle of throttling, the implementation code is as follows, and the following examples will be used in general:
Timestamp implementation
const throttle = function (fn, delay) {
let preTime = 0;
return function () {
const context = this;
const args = arguments;
const now = +new Date();
if(now - preTime > delay) { fn.apply(context, args); preTime = now; }}}Copy the code
Timer implementation
const throttle = function (fn, delay) {
let timeout = null
return function () {
const context = this;
const args = arguments;
if(! timeout) { timeout =setTimeout(function(){
timeout = null
fn.apply(context, args)
}, delay)
}
}
}
If you need to execute it immediately, change the order of execution
timeout = setTimeout(function(){
timeout = null
//fn.apply(context, args)
}, delay)
fn.apply(context, args)
Copy the code
MeContain. Onclick = throttle(log, 1000)
Have you found the characteristics of the throttle function at this time
- The timestamp is executed immediately and the timer is executed for the first time in n seconds
- There is no way to execute the event after the timestamp stops firing. The timer implementation will execute the event again even after it stops firing
Combine the two
const throttle = function (fn, delay) {
let timeout = null
let preTime = 0;
const later = function() {
preTime = +new Date()
timeout = null
fn.apply(context, args);
}
const throttled = function () {
const context = this;
const args = arguments;
const now = +new Date();
# Time remaining for the next fn trigger
const remaining = delay - ( now - preTime)
If there is no time left or the system time changes
if (remaining <= 0 || remaining > delay) {
if(timeout) {
clearTimeout(timeout)
timeout = null
}
preTime = now
fn.apply(context, args);
} else if(! timeout) { timeout =setTimeout(later, remaining)
}
}
throttled.cancel = function() {
clearTimeout(timeout);
previous = 0;
timeout = null;
}
return throttled
}
Copy the code
conclusion
Throttling, within a specified period of time, to ensure the execution of the function; When the event is triggered continuously and no event is triggered again within a certain period of time, the event handler function will be executed once. If the event is triggered again before the set time, the delay will start again
The document
Talk about function anti-shake function throttling function anti-shake function throttling
Sell yourself
Learn about Vue error handling Webpack DllPlugin to make build speed smooth and silky