Quickly implement debounce and throttle functions

Talking about js anti-shake and throttling

In the work project, we will definitely encounter a certain operation of the user, which will cause our function to be triggered frequently.
In fact, this is not what we want, and it is not desirable in terms of performance, and some may cause bugs. The common ones are the scroll bar of the page and the click of the button... Then can we reduce the trigger frequency of these functions through an operation? This
requires anti-shake and throttling . The
so-called anti- shake (debounce) means that the function can only be executed once within n seconds after the event is triggered. If the event is triggered again within n seconds, the function will be recalculated execution time.
Throttle (throttle) The
so-called throttling, refers to the continuous trigger event but only execute a function in n seconds. Throttling dilutes the frequency of execution of the function.

Let's talk about how to implement these two functions by listening to the scrolling of the browser, which will frequently trigger monitoring events.
A simple function for monitoring scroll events

  let count = 0;
  const showTop = () => {
    
    
    let top = document.documentElement.scrollTop;
    console.log(top, (count += 1));
  };
  
  window.onscroll = showTop;

Insert picture description here
Click the down button of the scroll bar, we will find that the monitoring function has been executed many times, but in fact we do not need such high-frequency feedback. After all, the performance of the browser is limited and should not be wasted here, so we will discuss how Optimize this scenario.

Debounce

Based on the above scenario, the first idea is first proposed: when the event is triggered for the first time, the function is not executed immediately, but a deadline value such as 200ms is given , and then:

  • If the scroll event is not triggered again within 200ms, then execute the function
  • If the scroll event is triggered again within 200ms, the current timing is cancelled and the timing is restarted

Effect : If a large number of the same event is triggered in a short time, the function will only be executed once.

Implementation : Since the timing is mentioned above, the key to implementation lies in the function setTimeout. Since a variable is also needed to save the timing, consider maintaining global purity. This can be achieved with the help of closures:

/**
  * 
  * @param callback 需要防抖的函数
  * @param time 延时的时间
  */
  const debounce = (callback: () => void, time: number) => {
    
    
    let timer: NodeJS.Timeout | null = null;
    console.log('timer', timer);
    return function() {
    
    
      if (timer) {
    
    
      	// 进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时
        clearTimeout(timer);  
      }
      // 每次执行setTimeou() 都会返回一个计时器的编号,用timer保存这个编号,用于清除计时器重新计时
      timer = setTimeout(callback, time);
      console.log('timer2', timer);
    };
  };
  // 然后是旧代码
  let count = 0;
  const showTop = () => {
    
    
    let top = document.documentElement.scrollTop;
    console.log(top, (count += 1));
  };
  
  window.onscroll = debounce(showTop,1000); 

At this point, you will find that you must stop scrolling for 1 second before printing the scroll bar position.

At this point, the anti-shake has been implemented, and now the definition is given :

For events that are triggered continuously in a short period of time (the above rolling event), the meaning of anti-shake is to make the event processing function execute only once within a certain time period (such as the above 1000 milliseconds) .

Throttling (throttle)

But if a user is bored and keeps dragging the scroll bar, then our event will never be triggered, this is not the effect we want, at this time we may want to even if the user keeps Triggering continuously, the event can also be executed once in a specific time interval, so that it can also achieve the effect we want.
The principle is roughly: we can design a function that is regularly open like a control valve, that is, after the function is executed once, it will temporarily fail for a certain period of time, and then reactivate after this period of time (similar to the skill cooling time ) .

Effect : If a large number of the same event is triggered in a short period of time, after the function is executed once, the function will no longer work within the specified time period, and will not take effect until this time has passed.

Implementation : Here is a simple implementation with the help of setTimeout, plus a status bit valid to indicate whether the current function is working:

/**
  * 
  * @param callback 需要防抖的函数
  * @param time 延时的时间
  */
  const throttle = (callback: () => void, time: number) => {
    
    
    let valid = true;
    return function() {
    
    
      if (!valid) {
    
    
        return false;
      }
      valid = false;
      setTimeout(() => {
    
    
        callback(), (valid = true);
      }, time);
    };
  };
  
  // 然后是旧代码
  let count = 0;
  const showTop = () => {
    
    
    let top = document.documentElement.scrollTop;
    console.log(top, (count += 1));
  };
  
  window.onscroll = throttle(showTop,1000);

Examples of other application scenarios

After talking about these two techniques, here are some scenarios that are often encountered in development:

  1. Search box input event, for example, to support input real-time search, you can use a throttling scheme (you must query related content after a period of time), or realize that the input interval is greater than a certain value (such as 500ms), as the user input is completed, and then the search starts Which scheme to use depends on business needs.
  2. The page resize event is commonly used when page adaptation is required. Dom rendering needs to be performed according to the final presentation of the page (in this case, anti-shake is generally used, because only the last change needs to be judged)

Original: https://segmentfault.com/a/1190000018428170

Guess you like

Origin blog.csdn.net/index_zhao/article/details/109627995