0

I am working on an application where I am making different window.postMessage() requests to pass messages. When I listen to a message with window.addEventListener('message', cb) I call another function, but some times I receive multiple calls to the function because it depends on how many times I post the message. I created a simple throttle function, which works well, but not for function calls. For instance, let's say when three times the function is called within 1000ms, the function should be called once and not three.

I am wondering this is the expected behavior, but in my case, the function is called three times.

I have used the throttle function from this answer, also this is the example fiddle I have created to see what I mean.

function throttle(func, wait, options) {
    var context, args, result;
    var timeout = null;
    var previous = 0;
    if (!options) options = {};
    var later = function () {
      previous = options.leading === false ? 0 : Date.now();
      timeout = null;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    };
    return function () {
      var now = Date.now();
      if (!previous && options.leading === false) previous = now;
      var remaining = wait - (now - previous);
      context = this;
      args = arguments;
      if (remaining <= 0 || remaining > wait) {
        if (timeout) {
          clearTimeout(timeout);
          timeout = null;
        }
        previous = now;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      } else if (!timeout && options.trailing !== false) {
        timeout = setTimeout(later, remaining);
      }
      return result;
    };
  }

  document.getElementById("btn").addEventListener(
    "click",
    throttle(function () {
      console.log("BUTTON CLICKED");
    }, 1000)
  );

  window.addEventListener("message", ({ data }) => {
    if (data.type === "viewer:clear:cache") {
      throttle(test(), 1000);
    }
  });

  function test() {
    console.log("TEST CALLED");
  }

  for (let i = 0; i < 5; i++) {
    window.postMessage({ type: "viewer:clear:cache" }, "*");
  }
    <button id="btn">CLICK ME</button>
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Nadeem Ahmad
  • 665
  • 3
  • 17
  • 40
  • Throttle and debounce are two different things: https://stackoverflow.com/questions/25991367/difference-between-throttling-and-debouncing-a-function – Felix Kling Sep 23 '20 at 12:26
  • Yes, I know. Am I using it somewhere ? @FelixKling – Nadeem Ahmad Sep 23 '20 at 12:27
  • I just mentioned it because you tagged the question with debouncing, so I was confused to what behavior you are looking for. It seems totally possible that the function is called more than once, even with throttle, depending on how you've configured it. Please include the relevant code in your question. We cannot really offer a solution if we don't know what you are actually doing. – Felix Kling Sep 23 '20 at 12:36
  • @FelixKling yes, that's the exact code fiddle that I created and shared. – Nadeem Ahmad Sep 23 '20 at 12:37

1 Answers1

1

Notice how in the click handler case you are passing the return value of throttle to addEventListener. In the message event case you are calling throttle inside the event handler and ignore the return value.

You are also not passing a function to throttle but the return value of test(). I.e. you are calling test first and then pass undefined to throttle. That's why test is called every time the message event handler is called.

What you need is:

window.addEventListener("message", throttle(({ data }) => {
  if (data.type === "viewer:clear:cache") {
    test();
  }
}, 1000));

throttle returns a new function and it's that function that needs to be called upon receiving an event.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143