JavaScript anti-shake and throttling explained

JavaScript anti-shake and throttling explained

Stabilization

The automatic door senses someone, opens the door, and starts a 5-second countdown. If another person approaches the door within 5 seconds, the door senses someone and starts a 5-second countdown again.

When an event is triggered, a delay is set. If the event is triggered again during this period, the delay is reset until the delay ends and the action is executed (to prevent multiple triggering)

On the web application

  • Statistics for changing page size
  • Statistics of scrolling page position
  • Control the number of requests for continuous input in the input box

At the beginning, click the button, console.log('pay money')

<body>
  <button id="btn">click</button>
</body>
<script>
  const btn = document.getElementById('btn')
  function payMoney() {
    console.log('pay money');
  }
  btn.addEventListener('click', payMoney)
</script>

Defining debounce

const btn = document.getElementById('btn')
function payMoney() {
  console.log('pay money');
}
function debounce(func) {
  // Return the function in the function, only return the function when clicked return function () {
    func()
  }
}
btn.addEventListener('click', debounce(payMoney))

Setting the delay

const btn = document.getElementById('btn')
function payMoney() {
  console.log('pay money');
}
function debounce(func, delay) {
  return function () {
    setTimeout(_ => func(), delay)
  }
}
btn.addEventListener('click', debounce(payMoney, 1000))

Clear Delay: Failed to execute

reason

Every time you click, the contents of the return function will be executed

The execution function of each click is independent and does not interfere with each other.

Because there is no connection between them, the clearing delay does not work here at all

To connect these independent execution functions, we need to use scope chains (closures)

const btn = document.getElementById('btn')
function payMoney() {
  console.log('pay money');
}
function debounce(func, delay) {
  return function () {
    let timer
    clearInterval(timer)
    timer = setTimeout(_ => func(), delay)
  }
}
btn.addEventListener('click', debounce(payMoney, 1000))

Put the timer outside the return function, so that timer variable is defined at the same time as the listening event is defined.

Because of the scope chain, all independent execution functions can access this timer variable.

And now this timer variable is only created once. It is unique. We just keep assigning values ​​to the timer to delay it.

Each clear delay clears the last defined delay, which is equivalent to multiple functions sharing the same external variable.

const btn = document.getElementById('btn')
function payMoney() {
  console.log('pay money');
}
function debounce(func, delay) {
  let timer
  return function () {
    clearInterval(timer)
    timer = setTimeout(_ => func(), delay)
  }
}
btn.addEventListener('click', debounce(payMoney, 1000))

In this code, this refers to window?

Because of the callback, the runtime is already under Window

const btn = document.getElementById('btn')
function payMoney() {
  console.log('pay money');
  console.log(this);
}
function debounce(func, delay) {
  let timer
  return function () {
    clearInterval(timer)
    timer = setTimeout(_ => func(), delay)
  }
}
btn.addEventListener('click', debounce(payMoney, 1000))

Solution

Save this before setTimeout. This time this points to the button.

const btn = document.getElementById('btn')
function payMoney() {
  console.log('pay money');
  console.log(this);
}
function debounce(func, delay) {
  let timer
  // This function is returned only when clicked, so this is the return function () pointing to the button {
    let context = this
    clearInterval(timer)
    timer = setTimeout(_ => {
      func.apply(context)
    }, delay)
  }
}
btn.addEventListener('click', debounce(payMoney, 1000))

Consider the parameter problem and add arg

const btn = document.getElementById('btn')
function payMoney() {
  console.log('pay money');
  console.log(this);
}
function debounce(func, delay) {
  let timer
  return function () {
    let context = this
    let args = arguments
    clearInterval(timer)
    timer = setTimeout(_ => {
      func.apply(context)
      console.log(context, args);
    }, delay)
  }
}
btn.addEventListener('click', debounce(payMoney, 1000))

Throttling

After triggering once, prevent multiple triggers in the future

Scrolling screen: Count the user's scrolling behavior to make corresponding web page responses

When users keep scrolling, requests will continue to be generated , and the number of requests will continue to increase, which can easily lead to network congestion.

We can execute the task immediately when the event is triggered , and then set a time interval limit . During this time, no matter how the user scrolls, the operation will be ignored.

After the time is up, if the user is detected to have scrolling behavior, the task will be executed again. And set the time interval

First, write a code that changes the page size and the background color of the page

function coloring() {
  let r = Math.floor(Math.random() * 255)
  let g = Math.floor(Math.random() * 255)
  let b = Math.floor(Math.random() * 255)
  document.body.style.background = `rgb(${r}, ${g}, ${b})`
}
window.addEventListener('resize', coloring)
function throttle(func, delay) {
  let timer
  return function () {
    timer = setTimeout(_ => {
      func()
    }, delay)
  }
}
window.addEventListener('resize', throttle(coloring, 2000))

Determine whether the triggered event is within the time interval

  • Not in: trigger event
  • In: No event is triggered
function throttle(func, delay) {
  let timer
  return function () {
    // timer is assigned a value, return directly, that is, do not execute the task if (timer) {
      return
    }
    // At this time, the timer has not been assigned a value, or the timer has been executed // Assign a value to the timer for delayed execution timer = setTimeout(_ => {
      func()
      // After the delay execution, we need to clear the value of timer timer = null
    }, delay)
  }
}
window.addEventListener('resize', throttle(coloring, 2000))

Solve this point (although the current example is under Window)

function throttle(func, delay) {
  let timer
  return function () {
    let context = this
    let args = arguments
    // timer is assigned a value, return directly, that is, do not execute the task if (timer) {
      return
    }
    // At this time, the timer has not been assigned a value, or the timer has been executed // Assign a value to the timer for delayed execution timer = setTimeout(_ => {
      func.apply(context, args)
      // After the delay execution, we need to clear the value of timer timer = null
    }, delay)
  }
}
window.addEventListener('resize', throttle(coloring, 1000))

Throttling core: event interval Another common time interval is to use the Date object

function throttle(func, delay) {
  // We need to compare with the previous time point to determine whether the time interval has passed // Outside the return function to avoid automatic modification every time it is executed let pre = 0
  return function () {
    // Save the time when the function is executed let now = new Date()
    // At the beginning, it will definitely execute if (now - pre > delay) {
      // The time interval has passed, and the function can be executed func()
      // After execution, reset the interval point pre = now
    }
  }
}
window.addEventListener('resize', throttle(coloring, 1000))

Solving parameter problems

function throttle(func, delay) {
  let pre = 0
  return function () {
    let context = this
    let args = arguments
    let now = new Date()
    if (now - pre > delay) {
      func.apply(context, args)
      pre = now
    }
  }
}
window.addEventListener('resize', throttle(coloring, 1000))

Summarize

This article ends here. I hope it can be helpful to you. I also hope that you can pay more attention to more content on 123WORDPRESS.COM!

You may also be interested in:
  • Analysis of JavaScript's anti-shake throttling function
  • What is JavaScript anti-shake and throttling
  • A brief discussion on JavaScript throttling and anti-shake
  • JavaScript anti-shake and throttling detailed explanation
  • Do you know about JavaScript anti-shake and throttling?

<<:  The process of building a Jenkins project under Linux (taking CentOS 7 as an example)

>>:  MySQL learning record: bloody incident caused by KEY partition

Recommend

The core process of nodejs processing tcp connection

A few days ago, I exchanged some knowledge about ...

MySQL method steps to determine whether it is a subset

Table of contents 1. Problem 2. Solution Option 1...

How to collect Nginx logs using Filebeat

Nginx logs can be used to analyze user address lo...

Experience in designing a layered interface in web design

Many netizens often ask why their websites always ...

HTML background color gradient achieved through CSS

Effect screenshots: Implementation code: Copy code...

Detailed explanation of the installation and use of Vue-Router

Table of contents Install Basic configuration of ...

nginx proxy_cache batch cache clearing script introduction

Preface: I used the official nginx proxy_cache as...

Vue implements file upload and download functions

This article example shares the specific code of ...

Detailed explanation of computed properties in Vue

Table of contents Interpolation Expressions metho...

Mobile front-end adaptation solution (summary)

I searched online and found that many interviews ...

Analysis and solution of data loss during Vue component value transfer

Preface In the previous article Two data types in...

HTML basics summary recommendation (paragraph)

HTML Paragraph Paragraphs are defined by the <...