Сценарии применения и реализация антишейков и троттлинга

внешний интерфейс JavaScript TypeScript

Стабилизатор

Anti-shake — это преобразование нескольких последовательных триггеров в течение определенного периода времени в один триггер.

сцены, которые будут использоваться

Как правило, его можно использовать для получения данных после того, как пользовательский ввод остановлен в течение определенного периода времени, а не каждый вход, как показано ниже:

код реализации

  function debounce<Return>(
    fn: (...params: any[]) => Return, 
    wait: number, /** 等待时间 */
    immediate: boolean /** 是否立刻执行一次 */
  ): Executor<Return> {
    const now: () => number = Date.now.bind(Date);
    let lastTime: number = 0;
    let timer: number = null;
    let params: IArguments = null;
    let _this: Function | null = null;

    function later(): void {
      const nowTime: number = now();

      if (nowTime - lastTime < wait) {
        // 如果还不够等待时间则继续等待
        const remainTime = wait - (nowTime - lastTime);

        timer = setTimeout(later, remainTime);
      } else {
        // 已到等待时间,执行回调
        debouncer.result = fn.apply(_this, params);

        timer = null;
        _this = null;
        params = null;
      }
    }

    function execute(): (Return | null) {
      lastTime = now();
      _this = this;
      params = arguments;

      try {
        if (immediate && timer === null) {
          // 立刻执行一次
          debouncer.result = fn.apply(_this, params);
        }

        return debouncer.result;
      } finally {
        if (timer === null) {
          // 加入时间队列,等待执行
          timer = setTimeout(later, wait);
        }
      }
    }

    // 创建执行器
    const debouncer: Executor<Return> = {
      execute,
      result: null,
    };

    return debouncer;
  };

Принцип очень простой, в основном определить, достигнуто ли время ожидания, и если нет, продолжить присоединяться к очереди задач и ждать выполнения. Инструкции:

import utils from '../index';

const input = document.querySelector('input');
const executor = utils.fn.debounce(function(value) {
  console.log('fetch');
  
  return value;
}, 300);

let value = null;

input.addEventListener('input', function(e) {
  executor.execute(e.target.value);
  value = executor.result;
});

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

дросселирование

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

сцены, которые будут использоваться

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

код реализации

throttle: function <Return>(
    fn: (...params: any[]) => Return,
    wait: number,
    {
      isExecuteAtStart = true,
      isExecuteAtEnd = true,
    }: ThrottleOptions = {
      isExecuteAtStart: true,
      isExecuteAtEnd: true,
    }
  ): Executor<Return> {
    let timer: number = null;
    let _this: Function = null;
    let params: IArguments = null;

    function execute(): (Return | null) {
      _this = this;
      params = arguments;

      if (isExecuteAtStart && timer === null) {
        // 如果需要开始的时候执行且没有计时器
        executor.result = fn.apply(_this, params);
        _this = null;
        params = null;
      }

      if (isExecuteAtEnd) {
        // 如果结束的时候需要执行
        if (timer === null) {
          timer = setTimeout(function () {
            executor.result = fn.apply(_this, params);
            _this = null;
            params = null;
            timer = null;
          }, wait);
        }
      }

      return executor.result;
    }

    const executor: Executor<Return> = {
      execute,
      result: null
    };

    return executor;
}

наконец

Цель защиты от сотрясения и регулирования — сократить количество ненужных вычислений, не тратить ресурсы впустую и выполнять вычисления триггеров только тогда, когда это уместно. Исходный код можно найти наэтот проектВ модуле fn вы можете видеть, что есть много практических функций, которые можно использовать и изучать. Если моя статья была вам полезна, ставьте лайк, спасибо~