1

The code below is intended to implement a throttle function in javascript but, for some reason is not working and the console.log(json) is only printed once... Could anyone help me out?

function throttle(cb, delay) {
  let shouldWait = false;
  return function() {
    if (shouldWait) return;
    cb();
    shouldWait = true;
    setTimeout(() => {
      shouldWait = false;
    }, delay);
  };
}

const fetchTodos = async() => {
  fetch("https://jsonplaceholder.typicode.com/todos/1")
    .then((response) => response.json())
    .then((json) => console.log(json));
};
const fetchTodosThrottled = throttle(fetchTodos, 1000);

for (let i = 0; i < 1000; i++) {
  fetchTodosThrottled();
}
jpxcar
  • 107
  • 1
  • 2
  • 7

2 Answers2

2

Throttling is intended to avoid excessive calls and so it is designed to skip calls when they come too quickly.

Since your code launches the 1000 calls all immediately, all but the first will be skipped. This is exactly what throttling is designed for. If you don't want calls to be skipped, then there are some other ways to do that:

Either wait for the fetch response to come in before making the next request:

const fetchTodos = async() => {
  return fetch("https://jsonplaceholder.typicode.com/todos/1")
    .then((response) => response.json())
    .then((json) => console.log(json));
};

(async () => {
  for (let i = 0; i < 10; i++) {
    await fetchTodos(); // wait for response before resuming the loop
  }
})();

Or, use setInterval or setTimeout to make requests with a preset pause between them:

const fetchTodos = async() => {
  return fetch("https://jsonplaceholder.typicode.com/todos/1")
    .then((response) => response.json())
    .then((json) => console.log(json));
};

(function loop(i) {
  if (i > 0) {
    fetchTodos();
    setTimeout(() => loop(i - 1), 1000);
  }
})(10);

You can also go for a mix of the two where you keep track of how many requests are still pending, and keep that number below a threshold. See:

trincot
  • 317,000
  • 35
  • 244
  • 286
0

As i understood your question: function runs only once, you should use setInterval javascript function (runs repeatedly) instead of setTimeout (runs once) Now imaging user pushing button for a several times, place a throttled button and it will not execute function each time.

  1. Use Interval not Timeout

    setInterval(() => { shouldWait = false; }, delay);

  2. For example, bind a event onclick to a button:

    on-click="throttle(fetchTodos, 1000)"

Dmitry Yudin
  • 1,033
  • 1
  • 10
  • 31