7

I am displaying a countdown watch with respect to a given endtime.

although its working perfect but i want to know which is best methods to apply.

below is my countdown function.

  var timerId;
  var postData = {endDate : endDate, tz : tz};  
  var countdown = function()
    { 
      $.ajax({
               type : 'post',
               async : false,
               timeout : 1000,
               url : './ajax_countdown.php',
               data : $.param(postData),
               dataType : 'json',
               success : function (resp){
                  $('#currentTime').html(resp.remainingTime);
               }
            }); 
     }

what i want is that function (countdown) shoud be called automatically after every 1 second and if it does not execute/completed within 1 second then cancel the current ajax and start a new ajax call.

now I found there are 4 working methods

method 1: using setInterval() with window object

window.setInterval(countdown, 1000);

method 2 : using setInterval() independently

setInterval(function() {countdown()}, 1000);

method 3 : using setTimeOut inside the function an call other function to intialize main function

var countdown = function() { 
     $.ajax({ //ajax code });
     timerId = setTimeout(countdown, 5000); // assign to a variable
 }

function clockStart() {  
        if (timerId) return
        countdown();
}
clockStart(); // calling this function 

method 4 : using anonymous function call

var countdown = function() { 
     $.ajax({ //ajax code });
     timerId = setTimeout(countdown, 5000);
 }
  (function(){
         if (timerId) return;
         countdown();
})();

Please tell me

  • What is con and pro of each method and which one is best/right method?
  • Should i use clearTimeOut() or clearInterval() ?

References

http://javascript.info/tutorial/settimeout-setinterval

Calling a function every 60 seconds

http://www.electrictoolbox.com/using-settimeout-javascript/

Community
  • 1
  • 1
xkeshav
  • 53,360
  • 44
  • 177
  • 245
  • 4
    I would consider 1 and 2 to be the same, with 1 being a cleaner approach. Similar for 3 and 4... whether you use an immediate function or not is more a matter of preference. I would call `countdown` immediately, no need to create an additional function. – Felix Kling Jul 17 '12 at 10:48
  • @FelixKling yup, that extra `function()` block is completely unnecessary, as is the `window.` qualifier (mostly). – Alnitak Jul 17 '12 at 10:50
  • @FelixKling so you are suggesting #1. – xkeshav Jul 17 '12 at 10:58
  • @diEcho I suggest using #1 as well, there is never any reason to wrap a function in an anonymous function like that. – Esailija Jul 17 '12 at 10:58
  • @diEcho: Only as "better" way compared to #2. But as I said, it's the same for me, the second one just appears to be a bit more convoluted. But whether to choose `setInterval` or `setTimeout` is a different question... – Felix Kling Jul 17 '12 at 11:02
  • 1
    @diEcho - This [fiddle](http://jsfiddle.net/LrGWz/1/) shows why delta timing is better than `setInterval`. – Aadit M Shah Jul 17 '12 at 12:12

3 Answers3

8

I wouldn't use any of your methods. The reason is setTimeout and setInterval do not guarantee that your code will execute after the specified delay. This is because JavaScript is single threaded.

If I need to call a function only once after a specified delay then I use setTimeout. However if I need to call a function after a fixed interval of time then I do not use setInterval. Instead I make use of delta timing. Here's the code.

The advantage of using delta timing is that your code will execute closer to the fixed interval of time you specify. It corrects itself. Creating and using a delta timer is simple. For example your code would be written as follows:

var timer = new DeltaTimer(function (time) {
    $.ajax({
        // properties
    });

    if (time - start >= 5000) timer.stop();
}, 1000);

var start = timer.start();

The above delta timer is better than setInterval (method 1), makes use of setTimeout (method 2) but also corrects itself, starts the timer using a function (method 3), and doesn't pollute the scope with a special clockStart function (method 4).

In addition you can easily get the exact time the function is called after the timer starts as the time the function is called is passed as an argument to the function. The timer also has a stop method to stop the timer. To start it again call start again.

Edit:

If you want to make the DeltaTimer look more like setInterval (start the timer automatically) you may implement a spawn function as follows:

DeltaTimer.spawn = function (render, interval) {
    var timer = new DeltaTimer(render, interval);

    var start = timer.start = function (start) {
        return function () {
            render.start = start();
        };
    }(timer.start);

    start();

    return timer;
};

Then you may automatically create and start the DeltaTimer as follows:

var timer = DeltaTimer.spawn(function countdown(time) {
    $.ajax({
        // properties
    });

    if (time - countdown.start >= 5000) timer.stop();
}, 1000);

Thus var timer = DeltaTimer.spawn(funct, delay); is equivalent to var interval = setInterval(funct, delay); and timer.stop(); is equivalent to clearInterval(interval);. I guess that's as much as you can automate it.

Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
  • +1; you really draw very good concept. but tell me how do i call this function directly. i dont want to call it. it shoud execute automatically – xkeshav Jul 17 '12 at 11:23
  • @diEcho - When you say that it should execute automatically what part of the above script are you trying to automate? There's not much room for automation but you may always create a [factory function](http://bonsaiden.github.com/JavaScript-Garden/#function.constructors "JavaScript Garden") and use that instead. – Aadit M Shah Jul 17 '12 at 11:28
  • i means that `countdown` function should start as well as page load. i dont want to initialize it with any event. – xkeshav Jul 17 '12 at 11:30
  • @diEcho - I edited my answer to describe how to start the timer automatically. – Aadit M Shah Jul 17 '12 at 11:51
6

The benefit of using #1 over #2 is that the window reference removes the chance of a scope variable overwriting setInterval.

// When out of global scope...
function setInterval() {

}

window.setInterval(foo, 100); // still calls the "correct" setInterval

There's no difference between wrapping the call to countdown in a function (#1, #2). #2 gives you greater flexibility as you can also call other functions/ pass arguments etc (although it's obviously trivial to swap from #1 to #2 if this becomes the case).

#4 saves you having to declare a function clockStart, other than that, it's the same as #3.

Use clearTimeout if you used setTimeout, and clearInterval if you used setInterval...

You should also be aware of how setTimeout and setInterval work differently. There's an amazing answer here which explains that...

As for what I'd use? I'd use #2.

Community
  • 1
  • 1
Matt
  • 74,352
  • 26
  • 153
  • 180
  • where do i write `clearInterval()` or `cleartimeOut()` respectively – xkeshav Jul 17 '12 at 10:53
  • What if `window` is a scope variable and not the global. The main point about them is the useless creation of an anonymous function imo. – Esailija Jul 17 '12 at 10:54
  • @Matt you are suggesting #2, whereas FelixKling suggesting #1 – xkeshav Jul 17 '12 at 10:55
  • @diEcho: It's `clearTimeout`, not `cleartimeOut`. Put them whereever you need to clear the timeout or interval? You need to pass it the value `setTimeout/setInterval` returned. – Matt Jul 17 '12 at 10:56
  • @diEcho: I don't know what you mean? If you need to cancel the interval for any reason, call `clearInterval`, if you don't, then... don't. – Matt Jul 17 '12 at 10:58
  • @Esailija: Heh, good point. All the different implementations are swings and roundabouts TBH, you've really got to nit-pick to choose the "best" one. – Matt Jul 17 '12 at 10:59
  • @Matt : my assumption : "If the execution is impossible, `setInterval()` is queued.so we use `clearInterval()`." is this right? – xkeshav Jul 17 '12 at 11:01
-1

if you are creating countdown then why u don't use jquery plugin and customize it according to your requirements? Checkout here

http://www.tripwiremagazine.com/2012/05/jquery-countdown-scripts.html

Muhammad Sannan Khalid
  • 3,127
  • 1
  • 22
  • 36
  • I have read this already. this is not useful in my case. i need to change each page as per user's timezone. – xkeshav Jul 17 '12 at 11:10