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

How to center your HTML button

How to center your HTML button itself? This is ea...

Summary of CSS usage tips

Recently, I started upgrading my blog. In the proc...

MySQL foreign key constraint (FOREIGN KEY) case explanation

MySQL foreign key constraint (FOREIGN KEY) is a s...

Docker installation tutorial in Linux environment

1. Installation environment Docker supports the f...

Solve the conflict between docker and vmware

1. Docker startup problem: Problem Solved: You ne...

Centering the Form in HTML

I once encountered an assignment where I was give...

HTML Tutorial: Collection of commonly used HTML tags (5)

These introduced HTML tags do not necessarily ful...

XHTML tutorial, a brief introduction to the basics of XHTML

<br />This article will briefly introduce yo...

How to design and create adaptive web pages

With the popularization of 3G, more and more peop...

HTML Grammar Encyclopedia_HTML Language Grammar Encyclopedia (Must Read)

Volume Label, Property Name, Description 002 <...

A brief discussion on the synchronization solution between MySQL and redis cache

Table of contents 1. Solution 1 (UDF) Demo Case 2...

Summary of Kubernetes's application areas

Kubernetes is the leader in the container orchest...

Example of implementing login effect with vue ElementUI's from form

Table of contents 1. Build basic styles through E...