0

I want my ajax call runed no often that 200 ms, so I wrote

if (update_timer != null) {
    // do nothing
} else {
    // update_timer == null
    update_timer = setTimeout (function () {perform_ajax_refresh()}, 200);
}

And in perform_ajax_refresh() function did:

function perform_ajax_refresh()
{
    clearTimeout(update_timer); 
    console.log(update_timer);
         // do ajax here
}

These 2 lines are my effort to kill the update_timer variable. What is the right way to do it??? I guess that clearTimeout makes no sence, but this is my effor to set update_timer variable to null.

Tigran
  • 1,049
  • 3
  • 15
  • 31
  • 1
    `clearTimeout` is perfect. –  Feb 15 '14 at 15:57
  • No, update_timer is not null after it and my if condition fail. – Tigran Feb 15 '14 at 15:58
  • 1
    So, the question is : "Why `update_timer` does not change to `null`?" right? –  Feb 15 '14 at 16:00
  • Is update timer in the same scope of both functions? – megawac Feb 15 '14 at 16:00
  • @megawac It's global. – Tigran Feb 15 '14 at 16:02
  • In this case we need more code. There is a hidden gap between the two samples you've posted, it's hard to figure out what's going wrong. –  Feb 15 '14 at 16:02
  • @wared - May be. I read documentation but still does not found that update_timer should change to null after clearTimeout run. – Tigran Feb 15 '14 at 16:03
  • `clearTimeout` has no effect on `update_timer`. This is the normal behaviour. The way you do is correct. Could you post more code? –  Feb 15 '14 at 16:04
  • Do a `console.log(update_timer)` in the `ajax_refresh` function and see if its defined. – megawac Feb 15 '14 at 16:04
  • I did: clearTimeout(update_timer); console.log(update_timer); And answer is 3. – Tigran Feb 15 '14 at 16:05
  • More code please. Still hard to see anything wrong. –  Feb 15 '14 at 16:07
  • So yes, it is defined. Sorry, code is big and this timer is user only in these 2 places. And at the begining, when it is defined as global :) – Tigran Feb 15 '14 at 16:07
  • Should it be null after call? – Tigran Feb 15 '14 at 16:09
  • 1
    What does "after call" means? After `clearTimeout` call? If so, the answer is "no". You have to set it to `null` by yourself. –  Feb 15 '14 at 16:13
  • Edited for more clarity (hopefully ^^') : http://stackoverflow.com/a/21800735/1636522. –  Feb 16 '14 at 06:54

4 Answers4

2

Javascript is pass-by-value, so it's impossible for clearTimeout to modify the variable passed as parameter.

Your concern is a valid one, and the simplest way to solve your problem is to set update_timer = null immediately after clearTimeout(update_timer).

(Also, avoid using global variables this way. When you're done with this, try to rewrite the code so that multiple such modules can live on one web page at the same time.)

Kos
  • 70,399
  • 25
  • 169
  • 233
1

Using a timeout-based solution, clearTimeout is the function to call.

Let me just suggest you another way. If you want any function run at most once every n msecs, you could use a throttling function. Here is a javascript implementation of such a function function. http://remysharp.com/2010/07/21/throttling-function-calls/

By using it, you do not have to implement the limiting logic inside the function that runs the ajax request, making your code easier to read and to reason about, and avoiding relying on state, which is nice.

var perform_ajax_refresh = function() 
    // your ajax call here
}
perform_ajax_refresh = throttle(perform_ajax_refresh, 200);
//the original perform_ajax_refresh now gets only executed at most once every 200 msecs

Here is the higher-order throttle function, taken from "remy sharp’s blog" that limits the function execution in time.

function throttle(fn, threshhold, scope) {
  threshhold || (threshhold = 250);
  var last,
      deferTimer;
  return function () {
    var context = scope || this;

    var now = +new Date,
        args = arguments;
    if (last && now < last + threshhold) {
      // hold on to it
      clearTimeout(deferTimer);
      deferTimer = setTimeout(function () {
        last = now;
        fn.apply(context, args);
      }, threshhold);
    } else {
      last = now;
      fn.apply(context, args);
    }
  };
}
Giovanni Filardo
  • 1,012
  • 8
  • 14
0

Clearing the timeout in the function body does nothing as the timeout has already happened at that time. Try this rather simple looking construct:

function perform_ajax_refresh()
{
    console.log("Refresh");
    // do ajax here

    // new timeout
    setTimeout(function () {perform_ajax_refresh()}, 200);
}
perform_ajax_refresh();
Skadi2k3
  • 66
  • 4
0

This title sounds like a movie!

Here is a "timer demo" : http://jsfiddle.net/wared/uVbb2/.

As you can see, there is a timer set to zero milliseconds. This trick is quite hard to explain but I believe that it deserves a little explanation. As it happens, I would say that without such a timer, when the countdown reaches zero, while is executed before span.innerHTML = sec + ' sec'... Yes, indeed, in the opposite way of the reading direction. Consequently, "0 sec" is never displayed since the countdown is erased immediately after, due to span.innerHTML = ''.

Roughly speaking, the DOM task is queued by default until there’s nothing left for the javascript engine to execute. The "0" timer allows to bypass this default behaviour by shifting the loop to the end of the execution queue, after the DOM task. I know that it can be confusing (and completely off-topic by the way), so, let me suggest you to read this :

Here is the code of the demo :

<button>click to play</button> <span></span>
var tid, span, button;
span = document.getElementsByTagName('span')[0];
button = document.getElementsByTagName('button')[0];
button.onclick = toggle;

function play(sec) {
    var i;
    span.innerHTML = sec + ' sec';
    if (sec) {
        tid = setTimeout(function () {
            play(--sec);
        }, 1000);
    } else {
        setTimeout(function () {
            i = 0;
            while (i++ < 5) alert('trapped :P');
            toggle();
        }, 0);
    }
}

function toggle() {
    if (tid) {
        clearTimeout(tid); // phew...
        tid = null;
        span.innerHTML = '';
        button.style.color = 'black';
        button.innerHTML = 'click to play';
    } else {
        play(5);
        button.style.color = 'red';
        button.innerHTML = 'DO NOT click me again!';
    }
}
Community
  • 1
  • 1