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 configure path alias for react scaffolding

The react version when writing this article is 16...

Docker nginx example method to deploy multiple projects

Prerequisites 1. Docker has been installed on the...

Specific steps to use vant framework in WeChat applet

Table of contents 1. Open the project directory o...

The hottest trends in web design UI in 2013 The most popular UI designs

Time flies, and in just six days, 2013 will becom...

The visual design path of the website should conform to user habits

Cooper talked about the user's visual path, w...

Analysis of MySQL duplicate index and redundant index examples

This article uses examples to describe MySQL dupl...

How to deploy your first application with Docker

In the previous article, you have installed Docke...

9 great JavaScript framework scripts for drawing charts on the web

9 great JavaScript framework scripts for drawing ...

How to call the browser sharing function in Vue

Preface Vue (pronounced /vjuː/, similar to view) ...

Three Vue slots to solve parent-child component communication

Table of contents Preface Environment Preparation...

Implementation of Docker packaging image and configuration modification

I have encountered many problems in learning Dock...

How to connect Navicat to the docker database on the server

Start the mysql container in docekr Use command: ...

Some experience in building the React Native project framework

React Native is a cross-platform mobile applicati...