function throttling, simply put, is to make a function cannot be called continuously within a short interval of time, only to make the next call to the function after the last function has passed the time interval you specified.
Function throttling principle is quite simple, it is estimated that everyone thought, that is the timer. When I trigger a time, settimout let the event delay for a while, and if the event is triggered at this interval, we clear out the original timer, then settimeout a new timer delay to execute, and so on.
The following scenarios are often triggered by frequent events, resulting in heavy behavior such as DOM operations, resource loads, and so on, causing the UI to pause and even the browser to crash.
1. Resize, scroll events for window objects
2. MouseMove event when dragging
3. Shooting games in the MouseDown, KeyDown events
4. Text input, automatic completion of KeyUp events
In fact, for window resize events, the actual demand is mostly to stop resizing n milliseconds to perform subsequent processing, while most of the other events need to perform subsequent processing at a certain frequency. There are two solutions to debounce and throttle in response to both of these requirements.
Throttle and Debounce are two solutions to the mismatch between request and response speed. The difference lies in the choice of different strategies.
Throttle performs functions at equal intervals.
Debounce time interval T Nejo triggers the event again, then the function is timed until the stop time is greater than or equal to T.
A simple realization of throttle function
Function Throttle (FN, threshhold, scope) {
Threshhold | | (threshhold =);
var last,
timer; return function () {
var context = Scope | |
var now = +new Date (),
args = arguments;
if (last && now-last + threshhold < 0) {
//hold in to it
cleartimeout (defertimer);
Timer = settimeout (function () {Last
= now;
Fn.apply (context, args);
}, threshhold);
else {Last
= now;
Fn.apply (context, args);}}
Call method
$ (' body '). On (' MouseMove ', throttle (function (event)
{
console.log (' tick ');
}, 1000));
The simple realization of debounce function
Function debounce (FN, delay)
{
var timer = null;
return function ()
{
var context = This,
args = arguments;
Cleartimeout (timer);
Timer = settimeout (function () {
fn.apply (context, args);
}, delay);
}
Call method
$ (' Input.username '). KeyPress (Debounce (function (event)
{
/do the Ajax request
}, 250));
Three, the simple encapsulation realization
/** * Throttle * @param fn, wait, debounce */var throttle = function (FN, wait, debounce) {
var timer = null,//Timer
t_last = NULL,////Last Set time
context,//contextual
args,//parameter
diff;//timing return
Funciton () {
var curr = + new Date ();
var context = This, args = arguments;
Cleartimeout (timer);
if (debounce) {//If it is debounce
timer = settimeout (function () {
fn.apply (context, args);
}, wait);
} else {//if it is throttle if
(!t_last) t_last = Curr;
if (curr-t_last >= wait) {
fn.apply;
context = wait = null;
}
} }}/** * debounce * @param fn, wait */var debounce = function (FN, wait)
{return
throttle (FN, wait, true);
}
Summary: These two methods apply to events that can be repeatedly triggered, such as Mousemove,keydown,keyup,keypress,scroll.
If only the native event is bound, not controlled, it will make the browser cotton, the user experience poor. In order to improve the performance of JS, it is recommended to use function throttling or function to control the above and similar events.
Iv. underscore v1.7.0 related source analysis
1. _.throttle function
_.throttle = function (func, wait, options) {var context, args, result;
var timeout = null;
Timer var previous = 0;
Last triggered time if (!options) options = {};
var later = function () {previous = Options.leading = = False? 0: _.now ();
timeout = null;
result = func.apply (context, args);
if (!timeout) context = args = null;
};
return function () {var now = _.now ();
The first time it executes if (!previous && options.leading = = false) previous = now;
Here we introduce a remaining concept: how long does it take to execute an event var remaining = wait-(now-previous);
context = this;
args = arguments; Remaining <= 0 takes into account the fact that when the event is stopped and/or is exactly the same as the wait, the event will be triggered immediately//remaining > The wait does not take into account the corresponding scene//Because now-previous will always be
Positive value, and not 0, then//remaining will always be smaller than wait, no more than the waiting situation//estimated to be safe, this situation is also immediately executed if (remaining <= 0 | | | remaining > Wait) {
if (timeout) {cleartimeout (timeout);
timeout = null;
} previous = Now;
result = func.apply (context, args);
if (!timeout) context = args = null; Whether to track} else if (!timeout && options.trailing!== false) {timeout = settimeout (later, remaining);
return result; };};
Visible from the above, underscore considered a lot of the situation: options.leading:
The first execution, the default is true, which means the first execution, and the incoming {Leading:false} disables the first execution of options.trailing: The last time it was executed, the default is true, which means the last execution, passing in {trailing: False} indicates that the last time you did not perform the so-called first execution is to trigger the event first, or to trigger the event, if you want to, the previous=0,remaining is negative, then call immediately the function is called the last execution, is the last time after the event, triggered this method, If you want to do so, set the timer, which is executed once after the event has ended. Remianing > Wait indicates that the client time has been modified.
2. _.debounce function
_.debounce = function (func, wait, immediate) {//immediate default to False var timeout, args, c
Ontext, timestamp, result; var later = function () {///When the _.debounce returns are called multiple times during the interval specified by the wait, the timestamp value is constantly updated, resulting in the last < wait && last >= 01
Straight to true, thus constantly starting a new timer delay execution func var last = _.now ()-timestamp;
if (last < then && last >= 0) {timeout = settimeout (later, wait-last);
else {timeout = null;
if (!immediate) {result = Func.apply (context, args);
if (!timeout) context = args = null;
}
}
};
return function () {context = this;
args = arguments;
timestamp = _.now (); The first time the method is invoked, and immediate is true, the Func function var callnow = Immediate &&!timeout is invoked;
The first time the method is called within the interval specified by the wait, the start timer calls the Func function if (!timeout) timeout = settimeout (later, wait) at timed intervals;
if (callnow) {result = Func.apply (context, args);
context = args = null;
return result;
};};
The highlight of _.debounce implementation I think is to adjust the delay execution of the call Func function by the recursive start timer instead of calling Cleartimeout.
The above is a small set to introduce JavaScript performance optimization function throttling (throttle) and function to shake (debounce), I hope to help you, if you have any questions please give me a message, small series will promptly reply to everyone. Here also thank you very much for the cloud Habitat Community website support!