Roman
Roman

Reputation: 149

Decorators in javascript

function debounce(f, ms) {
  let isCool = false;

  return function() {
    if (!isCool) {
      f.apply(this, arguments);
    }
    isCool = true;
    setTimeout(() => isCool = false, ms);
  };
}


let f = debounce(alert, 1000);

f(1); // runs immediately
f(2); // ignored


setTimeout(() => f(3), 100); // ignored ( only 100 ms passed )
setTimeout(() => f(4), 1100); // runs
setTimeout(() => f(5), 1500); // ignored (less than 1000 ms from the last run)

The result of debounce(f, ms) decorator should be a wrapper that passes the call to f at maximum once per ms milliseconds. When we call a “debounced” function, it guarantees that all future calls to the function made less than ms milliseconds after the previous call will be ignored. Why my code doesn't working as it should be? It should ignore call to f(5), instead it runs...

Upvotes: 1

Views: 195

Answers (1)

RamblinRose
RamblinRose

Reputation: 4963

@deceze's comment answers your question. I'll add that there's no reason to complicate matters with setTimeout. Simply track time between invocations.

function debounce(f, ms) {
  let lastApply = 0;
  const cooldownMs = ms;
  return function() {
    let now = Date.now();
    if ((now - cooldownMs) >= lastApply) {
      lastApply = now;
      f.apply(this, arguments);
    }
  };
}


let f = debounce(console.log, 1000);

f(1); // runs immediately
f(2); // ignored


setTimeout(() => f(3), 100); // ignored ( only 100 ms passed )
setTimeout(() => f(4), 1100); // runs
setTimeout(() => f(5), 1500); // ignored (less than 1000 ms from the last run)

Upvotes: 1

Related Questions