4

I use the function below to check on the status of a JSON file. It runs every 8 seconds (using setTimeout) to check if the file has changed. Once the JSON's status becomes 'success' I no longer want to keep calling the function. Can someone please show me how to do this? I suspect it involves the use of clearTimeout, but I'm unsure how to implement this.

Cheers!

  $(function() {
    var checkBookStatus = function() {
       var job_id = "#{@job.job_id}";
       var msg = $('.msg');
       var msgBuilding = $('#msg-building');
       var msgQueuing = $('#msg-in-queue');
       var msgSuccessful = $('#msg-successful-build');
       var msgError = $('#msg-error'); 
       $.ajax({ 
         url: '/jobs/'+job_id+'/status.json',

           datatype: 'JSON',
           success:function(data){
             if (data.status == "failure")  {
               msg.hide();          
               msgError.show();
             }
             else if (data.status == "#{Job.queue}")  {
            msg.hide();          
            msgQueuing.show();
         }
             else if (data.status == "#{Job.building}")  {
            msg.hide();          
            msgBuilding.show();
         }             
         else if (data.status == "#{Job.failure}")  {
             msg.hide();          
             msgError.show();
         }
         else if (data.status == "#{Job.success}")  {
             msg.hide();          
             msgSuccessful.show();

              }                    
           },       
       }).always(function () {
            setTimeout(checkBookStatus, 8000);
      });
    };    
   checkBookStatus();    
  });
swisstony
  • 1,667
  • 3
  • 18
  • 27

6 Answers6

6

t = setTimeout(checkBookStatus, 8000); when you decide to stop the timeout use this clearTimeout(t);.

Ahmed Jolani
  • 2,872
  • 2
  • 20
  • 24
  • make sure that it's `t = setTimeout(...)` not `var t = setTimeout(...)` the `t` must be set as global variable. – Ahmed Jolani Apr 30 '12 at 07:54
  • the timeout will call checkBookStatus function, the clear must be inside the checkBookStatus function, it's obvious that the clearing for the timeout won't happen unless the function is called "already called", why would he ask to stop it if it's not called yet? – Ahmed Jolani Apr 30 '12 at 08:00
  • @LeeKowalkowski you made me think about it over and over man! when he first call the function, and then outside the function var t would be created and accessible, after the first call setTimeout would be fired so, outside he could like count then use clearTimeout(t) and that would be valid after the first call of course. – Ahmed Jolani Apr 30 '12 at 08:11
  • The `always()` function will set a new, different timeout though. That's the problem. As the code currently stands, there's no way to know to clear the timeout. – Lee Kowalkowski Apr 30 '12 at 08:14
  • The *value* of `t` needs to match an active pending timeout though. If you do `t=setTimeout(); t=setTimeout(); clearTimeout(t);` You have 2 timeouts but have only cleared the latter. Using `timeout` for iteration is always going to be more complicated. – Lee Kowalkowski Apr 30 '12 at 08:32
  • then using a counter, `c=0;` outside, now before calling the timeout check on the counter and after calling increment the counter `c`. – Ahmed Jolani Apr 30 '12 at 08:34
  • That's irrelevant, *how* do you know to clear the timeout *outside* of the function, when the data you need to make that decision is *inside* the function? – Lee Kowalkowski Apr 30 '12 at 08:43
  • In my last comment I didn't wanna clear the timeout, I just wanted to stop setTimeout from being called, but I got your point now, your solution is the correct one. – Ahmed Jolani Apr 30 '12 at 09:03
5

use clearTimeout

e.g. you defined :

id = setTimeout(checkBookStatus, 8000);  

then you can remove this function by :

clearTimeout(id)
Siwei
  • 19,858
  • 7
  • 75
  • 95
2

Call clearTimeout with the value previously returned by setTimeout. This would give you something like:

$(function() {
  var timeoutID;
  var checkBookStatus = function () {
      […]
      else if (data.status == "#{Job.success}")  {
          clearTimeout(timeoutID);
      […]
       }).always(function () {
        timeoutID = setTimeout(checkBookStatus, 8000);
      […]
kmkaplan
  • 18,655
  • 4
  • 51
  • 65
2

When you use setTimeout, use like this:

var myTime = setTimeout(checkBookStatus, 8000);

to clear it just:

clearTimeout(myTime);
Mihai Iorga
  • 39,330
  • 16
  • 106
  • 107
2

Before your call of checkBookStatus() at the end, put another call: var interval = setInterval(checkBookStatus, 8000);. Then on success you can clearInterval(interval).

Do not use setTimeout for iteration.

A lot of answers are suggesting just to use clearTimeout() however, you are checking the status after the timeout has expired, there is no timeout to clear. You need to not call setTimeout() in your always() function rather than to clear anything. So you could re-inspect the status inside your always() function I suppose, but your data object isn't in scope there. It would be preferable to just use setInterval() outside of your checkBookStatus() function.

$(function() {
    var checkBookStatus = function() {
        var job_id = "#{@job.job_id}";
        var msg = $('.msg');
        var msgBuilding = $('#msg-building');
        var msgQueuing = $('#msg-in-queue');
        var msgSuccessful = $('#msg-successful-build');
        var msgError = $('#msg-error'); 
        $.ajax({ 
            url: '/jobs/'+job_id+'/status.json',
            datatype: 'JSON',
            success:function(data){
                if (data.status == "failure")  {
                    msg.hide();          
                    msgError.show();
                }
                else if (data.status == "#{Job.queue}")  {
                    msg.hide();          
                    msgQueuing.show();
                }
                else if (data.status == "#{Job.building}")  {
                    msg.hide();          
                    msgBuilding.show();
                }             
                else if (data.status == "#{Job.failure}")  {
                    msg.hide();          
                    msgError.show();
                }
                else if (data.status == "#{Job.success}")  {
                    msg.hide();          
                    msgSuccessful.show();
                    clearInterval(interval);
                }                    
            }       
        });
    };    
    var interval = setInterval(checkBookStatus, 8000);    
    checkBookStatus();
});
Lee Kowalkowski
  • 11,591
  • 3
  • 40
  • 46
0

the following should work...

the setTimeout function return an instance of the setTimeout function. Keep this value in a variable and pass it to the function clearTimeout when you want to prevent the event from firing again.

i.e.

    var t = setTimeout(1000, someFunction);
...

//after you no longer need the timeout to fire, call

clearTimeout(t);
Heshan Perera
  • 4,592
  • 8
  • 44
  • 57