Возвращает отклоненную версию входной функции

Пожалуйста, помогите мне решить проблему, как мы можем вернуть отклоненную версию функции ввода. проверьте код ниже:

const steven = () => {console.info('steven')}
  const debounce = (fn, timeLimit) => {
    // what should come here?
    }
const debouncedSteeven = debounce(steven, 5000) // returns a debounced version of the input function
window.addEventListener('scroll', debouncedSteeven);

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

Shidersz 18.04.2019 21:24

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

Jagdeesh Kumar 18.04.2019 21:28

Проводили ли вы какое-либо исследование debounce или пытались что-то реализовать самостоятельно?

Bergi 18.04.2019 22:09
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
3
281
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Посмотрите на setTimeout, который в основном делает то, о чем вы просите.

const debounce = (fn, timeLimit) => () => {
  clearTimeout(this.timeout);
  this.timeout = setTimeout(fn, timeLimit);
};

let myFunc = () => console.info('yo');
let myFuncDebounced = debounce(myFunc);
myFuncDebounced();
myFuncDebounced();
console.info('this will print first cause this aint Tha BOUNCE d!!!');

Это не отменено — многократный вызов функции под timeLimit будет по-прежнему выполняться один раз за каждый сделанный вызов.

VLAZ 18.04.2019 21:47

фиксированный. спасибо, что указали на это

junvar 18.04.2019 22:21
Ответ принят как подходящий

Если я правильно понял, вы хотите, чтобы функция выполнялась, если нет события scroll более X миллисекунд. В этом случае одним из решений является использование setTimeout() и clearTimeout(). Таким образом, каждый раз, когда вызывается функция debounce, timeout сбрасывается, если он уже существует. Реализация будет примерно такой:

// Object to hold the timers by function names.
let timers = {};

const steven = () => {console.info('steven')};

const debounce = (fn, timeLimit) =>
{
    return () =>
    {
        if (timers[fn.name])
            clearTimeout(timers[fn.name]);

        timers[fn.name] = setTimeout(fn, timeLimit);
    }
}

const debouncedSteeven = debounce(steven, 5000);
window.addEventListener('scroll', debouncedSteeven);
.as-console {background-color:black !important; color:lime;}
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>

Если вместо этого вы хотите выполнить функцию, если между двумя событиями X есть промежуток в scroll миллисекунд, вы можете попробовать это:

// Object to hold last time a debounced method is called.
let lastExec = {};

const steven = () => {console.info('steven')};

const debounce = (fn, timeLimit) =>
{
    return () =>
    {
        if (new Date().getTime() - lastExec[fn.name] > timeLimit)
            fn();

        lastExec[fn.name] = new Date().getTime();
    }
}

const debouncedSteeven = debounce(steven, 5000);
window.addEventListener('scroll', debouncedSteeven);
.as-console {background-color:black !important; color:lime;}
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>

Спасибо за ваш ответ, но он автоматически регистрирует Стивена через некоторое время. Я хочу регистрировать Стивена только после прокрутки пользователя и сделать перерыв более 5 секунд.

Jagdeesh Kumar 18.04.2019 22:00

@JagdeeshKumar О, понятно, проверьте второй фрагмент в обновленной версии.

Shidersz 18.04.2019 22:07

Работал на меня. Спасибо!

Jagdeesh Kumar 19.04.2019 11:33

Я думаю, что лучшее решение с rxjs сначала установите rxjs с помощью npm или yarn. затем создайте наблюдаемое из события прокрутки и передайте оператор debounce, а внутри его функции - оператор таймера, все они импортированы из rxjs.

fromEvent(window, 'scroll')
  .pipe(debounce(() => timer(1000))
  .subscribe(v => console.info('scrolled'))

этот код будет регистрировать «прокручиваемый» со временем устранения дребезга 1000 мс = 1 сек. также рекомендуется отписываться в конце жизненного цикла компонента или кода, чтобы предотвратить утечку памяти.

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

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

function debounce(fn, limit = 0) {
  //this will hold the timer identifier from setTimeout
  let timeId;
  
  //return a debounced function
  return function _debounced() {
    //unschedule any previous execution
    clearTimeout(timeId);
    
    //store the arguments
    const args = arguments;
    
    //store the context
    let ctx = this;
    
    //schedule a new execution after the given time limit
    timeId = setTimeout(function() {
      //run the function with the context and arguments passed
      fn.apply(ctx, args);
    }, limit);
  }
}


//using parameters
function add(a, b) {
  console.info("adding", a, b);
  console.info("result", a + b);
}

const debouncedAdd = debounce(add, 1000);

debouncedAdd(1, 2);
debouncedAdd(3, 4);
debouncedAdd(5, 6); //only this gets executed

//using context
const person = {
  name: "Alice",
  sayHello: debounce(function sayHello() {
    console.info("hello, my name is:", this.name)
  }, 1000)
}
  
person.sayHello();
person.name = "Bob";
person.sayHello();
person.name = "Carol";
person.sayHello(); //only this gets executed

Хорошо, та же идея, что и у меня, но более общий подход. Я просто не могу понять, как удалить мой глобальный объект, используемый для хранения ids, возвращаемого из setTimeout, и теперь я вижу, как это сделать (+1). В любом случае, я думаю, что ОП хотел другого...

Shidersz 18.04.2019 22:25

Другие вопросы по теме