Talking about the difference between _.throttle and _.debounce in Underscore.js

Source: Internet
Author: User

Underscore.js is a very lean library, only 5.2KB after compression. It provides dozens of functional programming methods to compensate for the shortcomings of the standard library and greatly facilitates the programming of JavaScript.

This paper only discusses the principle, effect and use of the two functional methods of Underscore.js _.throttle and _.debounce.

The usual function (or method) invocation process is divided into three parts: request, execute, and response. (In the text "request" and "call" synonymous, "response" and "return" synonymous, in order to better express, deliberately use the claim and response. )

In some scenarios, such as events that respond to mouse movements or window resizing, the trigger frequency is high. If the slightly complex processing function, the need for more computation execution time, the response speed can not keep up with the trigger frequency, often there will be delays, resulting in suspended animation or a sense of Kaka.

When computing resources are not enough, the most intuitive solution is to upgrade the hardware, admittedly, through the purchase of better hardware can solve some problems, but also need to pay a high cost. In particular, the client and server models require the client to upgrade the hardware basically impossible.

With limited resources, processing functions cannot respond to high-frequency calls in real time. Second, is it possible to respond only to part of the request? Dense requests under certain scenarios have strong homogeneity and continuity. For example, the trajectory parameter of the mouse movement. The more timely the response, the smoother the effect, but if the response is not as fast as it should be, it will appear to be a bit more smooth if the appropriate discard some requests.

Throttle and Debounce are the two scenarios that address the mismatch between request and response speed. The difference between the two is to choose a different strategy.

Elevator timeout

Imagine the elevator underneath the office building every day. The elevator is delivered once, analogous to the execution and response of a function. Assume that the elevator has two operating strategies ' throttle ' and ' debounce ', with a timeout of 15 seconds, regardless of the capacity limit.

Throttle strategy for elevators. Ensure that if the elevator first person comes in, 15 seconds after delivery on time, do not wait. If there is no one, then standby.

Debounce strategy for elevators. If someone comes in the elevator, wait 15 seconds. If another person comes in, 15 seconds waits for a re-timer until 15 seconds expires and the shipment begins.

Using the example

_.throttle Use Example

function log (event) {  console.log (window). scrolltop (), event.timestamp);};/ /Console Record window scrolling events, the trigger frequency is faster than you think $ (window). scroll (log);//Console Records window scrolling events, triggering a maximum of $ (window) per 250ms. Scroll (_.throttle (log, 250));

  

_.debounce Use Example

function Ajax_lookup (event) {  //to input content $ (this). Val () performs AJAX queries};//character input is faster than you expected, and AJAX requests are too late to reply. $ (' Input:text '). KeyUp (ajax_lookup);//When the user pauses for 250 milliseconds to start looking for $ (' Input:text '). KeyUp (_.debounce (ajax_lookup. 250));

  

Underscore source annotations

Let's read the source code and find out what it is. Based on the development version (1.7.0) of the source code, added some comments to help understand.

_.throttle method source Code

javascript/** * Frequency control when a continuous call is returned from a function, the Func execution frequency is limited to times/wait * * @param {function} func passed in function * @param {number} wait Represents the time window interval * @param {object} options if you want to ignore calls on the start boundary, pass in {leading:false}. * If you want to ignore the call on the end boundary, pass in {trailing:false} * @return {function} to return the client call function */_.thrott  Le = function (func, wait, options) {var context, args, result;  var timeout = null;  Last execution time point var previous = 0;  if (!options) options = {};    Deferred execution function var later = function () {//If the start boundary is set to not execute option, the last execution time is always 0 previous = Options.leading = = = False? 0: _.now ();    timeout = null;    result = func.apply (context, args);  if (!timeout) context = args = null;  };    return function () {var now = _.now ();    When first executed, the last execution time is set to the current time if the start boundary is set to not execute option.    if (!previous && options.leading = = = False) previous = now;    Delay execution time interval var remaining = wait-(now-previous);    context = this;    args = arguments; The delay interval remaining is less than or equal to 0, indicating that more than one time interval has elapsed since the last execution of thisWindow//remaining is greater than the time window wait, indicating that the client system time has been adjusted if (remaining <= 0 | | remaining > Wait) {cleartimeout (timeout);      timeout = null;      previous = now;      result = func.apply (context, args);    if (!timeout) context = args = null; If deferred execution does not exist, and no end bounds are set, the option} else if (!timeout && options.trailing!== false) {timeout = SetTimeout (later    , remaining);  } return result; };};

 

_.debounce method source Code

javascript/** * Idle control return function Continuous call, idle time must be greater than or equal to Wait,func to execute * * @param {function} func pass in function * @param {number} Wai T represents the interval of the time window * @param {Boolean} immediate is set to Ture, the call fires at the start boundary instead of the end boundary * @return {function} returns the client call function */  _.debounce = function (func, wait, immediate) {var timeout, args, context, timestamp, result;    var later = function () {//According to last trigger time interval var = _.now ()-timestamp; The last time the wrapper function was called is less than the set time interval, wait, {timeout = setTimeout {0}} (later, wait-    last);      } else {timeout = null;        If set to Immediate===true, because the start boundary has already been called, there is no need to call if (!immediate) {result = Func.apply (context, args);      if (!timeout) context = args = null;  }    }  };    return function () {context = this;    args = arguments;    timestamp = _.now ();    var callnow = immediate &&!timeout;    If the delay does not exist, reset the delay if (!timeout) timeout = SetTimeout (later, wait); if (callnow) {result = Func.Apply (context, args);    context = args = null;  } return result; };};

  

Visual presentation

Each row in the example draws the timeline at 30ms, and the first line, MouseMove events, is the reference datum that outputs the loop-visible ASCII character on the timeline at 50ms per response frequency.

When the mouse enters the left square (MouseEnter event) All lines begin to draw the timeline, the mouse shake (MouseMove event) draws a block of characters on the timeline, and each word converts sequential blocks indicates that the event was triggered once. In order to show the delay trigger effect, the presentation and text of the adjacent character converts sequential blocks are different.

The top two buttons ' trigger 1 times every 100 milliseconds ' and ' trigger 2 times every 200 milliseconds ' demonstrate the effect of triggering events at constant frequency at a constant speed.

Demo Address: http://throttle-debounce.coding.io/]http://throttle-debounce.coding.io/

Source Address: https://coding.net/u/duwan/p/throttle-debounce/]https://coding.net/u/duwan/p/throttle-debounce/

Usage Scenarios

These two functions can be taken into account as long as they are involved in a continuous event or frequency control-related application, such as:

Game shooting, KeyDown event text input, AutoComplete, KeyUp event mouse movement, MouseMove event DOM element Dynamic positioning, Window object resize and scroll events

The former two debounce and throttle can be used on demand, the latter two must be used throttle. If you do not do the filtering process, each second will trigger the corresponding event dozens of times. In particular, the MouseMove event can trigger an event every time a pixel is moved. If you are doing a mouse-related application on a canvas, filtering event processing is a must, otherwise it will definitely lead to a bad experience.

Reference reading

1. underscore. JS

2. higher-order functions debounce and throttle

3. JQuery Throttle/debounce:sometimes, Less is more!

4. Debounce and Throttle:a visual explanation

Vangie Du

The future of you, will be grateful to now desperately strive for their own!

Talking about the difference between _.throttle and _.debounce in Underscore.js

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.