Что такое троттлинг и антишейк и сценарии их использования

JavaScript
Что такое троттлинг и антишейк и сценарии их использования

1. Дросселирование

Она может быть запущена только один раз в течение определенного периода времени. Если в течение этого периода происходит несколько событий, функция обратного вызова будет запущена только тогда, когда она вступит в силу в первый раз, и ее можно будет запустить снова через определенный период времени ( в первый раз он вступает в силу в течение n секунд).

Например: карусельная карта 98k нажмите один раз, чтобы выстрелить и один раз, чтобы сменить пули, вы не можете стрелять в период навыков героя славы короля.

Код:

function throttle(fn,delay){
  let flag = true;

  return function(){
    if(flag){
      flag = false;
      setTimeout(() =>{
        flag = true
      },delay)
      return fn()
    }
  }  
}

Эффект: даже если большое количество одного и того же события инициировано в течение определенного периода времени, после того, как функция обратного вызова будет выполнена один раз, функция обратного вызова больше не будет работать в течение указанного периода времени, и она не будет действовать снова до этого периода. истекает.

2. Защита от сотрясений

Когда событие срабатывает, функция обратного вызова срабатывает после задержки n секунд.Если событие срабатывает снова в течение n секунд, время расчета будет перезапущено (последний раз, когда оно вступает в силу в течение n секунд)

Например: возвращение короля, функция поиска поля ввода, событие изменения размера страницы

Код:

function debounce(fn,delay){
  let timer = null;
  return function(){
    if(timer){
      clearTimeout(timer)
    }
    timer = setTimeout(fn,delay)
  }
}

Эффект: в течение определенного периода времени, независимо от того, сколько раз вы запускаете событие, функция обратного вызова выполняется только один раз.

3. Примеры

Напишите пример, чтобы использовать вышеупомянутое дросселирование и антикровь 💡

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .box{
      width: 90%;
      height: 200px;
      outline: blanchedalmond 1px solid;
      margin: 10px auto;
      padding: 20px;
      box-sizing: border-box;
    }
    .container{
      height: 60px;
      margin-top: 20px;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
    .aa{
      width: 60px;
      height:60px;
      text-align:center;  
      color: white;
    }
    .aa>div{
      width: 60px;
      height: 40px;
    }
    #target{
      background-color: coral;
    }
    #home{
      background-color: aqua;
    }
    #bullet{
      width: 60px;
    }
    #bullet>div{
      position: absolute;
      left: calc(5% + 20px);
      width: 30px;
      height: 10px;
      background-color: dimgrey;
    }
    #hanxin{
      text-align: center;
      position: relative;
      left: 0px;
    }

    .send{
      animation: move 1s linear;
      animation-fill-mode: forwards;
    }
    @keyframes move
    {
      to {left: calc(90% - 35px);}
    }
  </style>
</head>
<body>
  <div class="box">
    <h2>节流</h2>
    <button id="shoot">发射</button>
    <text id="text1">子弹已就绪</text>
    <div class="container">
      <div id="bullet">手枪
      </div>
      <div class="aa" id="target">目标
        <div></div>
      </div>
    </div>
  </div>
  <div class="box">
    <h2>防抖</h2>
    <button id="back">回城</button>
    <text id="text2">英雄未回城</text>
    <div class="container">
      <div id="hanxin">韩信</div>
      <div class="aa" id="home">泉水
        <div></div>
      </div>
    </div>
  </div>
</body>
<script>
let bullet = document.querySelector('#bullet');
let hanxin = document.querySelector('#hanxin');
let shoot = document.querySelector('#shoot');
let back = document.querySelector('#back');

let text1 = document.querySelector('#text1')
let text2 = document.querySelector('#text2')

// 节流
// 两个参数分别是 要执行的回调函数,间隔时间
function throttle(fn,delay){
  let flag = true;

  return function(){
    if(flag){
      flag = false;
      text1.textContent = '子弹上膛中'
      setTimeout(() =>{
        flag = true
        text1.textContent = '子弹已就绪'
      },delay)
      return fn()
    }
  }  
}

// 防抖
function debounce(fn,delay){
  let timer = null;
  return function(){
    if(text2.textContent === '英雄已回城'){
      return alert('韩信已经回城了,刷新页面再来试一下吧!')
    }
    if(timer){
      clearTimeout(timer)
    }
    text2.textContent = '英雄回城中'
    timer = setTimeout(fn,delay)
  }
}

// 射击事件
function shooting(){
  var zd  = document.createElement("div")
  bullet.appendChild(zd).classList.add('send')
}

// 回城事件
function goHome(){
  hanxin.style.left = 'calc(100% - 60px)';
  text2.textContent = '英雄已回城'
}

let a = throttle(shooting,2000)
shoot.addEventListener('click',a)

let b = debounce(goHome,3000)
back.addEventListener('click',b)
</script>
</html>

Изображение эффекта:

Вы можете видеть, что после того, как пуля выстрелила, вам нужно подождать некоторое время ⏱, чтобы снова выстрелить.

Когда Хань Синь вернется в город, снова нажимаем кнопку возврата, и время возврата будет пересчитано⏱

4. Резюме

  • Дросселирование заключается в выполнении обратного вызова сразу после срабатывания события, и он может быть запущен снова через некоторое время.В течение этого периода, независимо от того, сколько раз событие запускается, обратный вызов не будет выполняться (аналогично кулдауну навыков героя).
  • Anti-shake означает, что после срабатывания события callback выполняется через промежуток времени, в течение которого событие срабатывает снова, и время будет пересчитано (аналогично возвращению героя в город).
  • Роль дроссельной заслонки и функции защиты от сотрясения заключается в предотвращении множественных вызовов.