3

I have an Ajax request waiting for response from another process.

function test() {
    var flag = 0;
    while (flag === 0) {
        $.ajax({
            url: "cs/CheckForProcess",
            async: false,
            success: function(data) {
                if (data !== 'NotReady') {
                    $('#results').html(data);
                    flag = 1;
                } else {
                    $('#results').html('<h1>Processing...</h1>');
                    setTimeout(function() {
                    }, 6000);
                }
            }
        });
    }
}

the problem is that the setTimout isnt working although i see in debug mode that the else condition is executed.


EDIT: i want the next ajax request to be sent only 6 seconds after validating the process is not ready.

what am i missing? Thx.

Danny Valariola
  • 1,118
  • 5
  • 26
  • 41

3 Answers3

9

setTimeout is an async function. It does not pause your script. Your script will continue to run (and 6000ms later your setTimeout callback function will execute).

You could consider using setInterval to keep checking for your other condition to be true.

You could probably remove async:false by keeping track of your server response elsewhere. Once you have a successful callback then you should cancel the interval.

function test() {
    var timerId = 0,
    timerId = setInterval(function(){
        $.ajax({
            url: "cs/CheckForProcess",
            success: function(data) {
                if (data !== 'NotReady') {
                    $('#results').html(data);
                    clearInterval(timerId);
                }
            }
        });
    }, 6000)
}
jaredrada
  • 1,130
  • 3
  • 12
  • 25
  • can you please explain why are you clearing the interval in the "else" statement? – Danny Valariola Nov 03 '13 at 18:10
  • This could have an issue if the ajax call took a long time to return (e.g. the server got slow or the network had a hiccup) in that multiple ajax calls could pile up. It is generally better to start the next ajax call only after the current one finishes rather than blindly kick them off on a timer without regard for whether the previous one has completed or not. – jfriend00 Nov 03 '13 at 18:29
  • 1
    @DannyValariola I've updated the answer so when successful data is returned we cancel the interval so the ajax calls will stop. That is to say, we cancel when data !== 'NotReady' – jaredrada Nov 03 '13 at 18:29
3

Javascript does not have the ability to sleep (e.g. suspend or block javascript execution) using setTimeout.

A setTimeout() schedules a function to run sometime in the future and other javascript just happily keeps running during that time.

What you should do is use setTimeout() to schedule the next run of your ajax function if the data was not yet ready. So, when there is no data ready, you schedule the next ajax call for 6 seconds from now, but when you do get the data, you just process the data and you're done.

In addition, you really don't want to use async: false because that freezes the browser (doesn't allow any other processing to occur) during the ajax call. This same operation can be written to leverage the asynchronous nature of ajax and allow you to still solve your problem, but allow other processing to continue in the browser with no browser blocking. This requires asynchronous programming techniques.

You can do so like this:

function test() {

    function runIt() {
        $.ajax({
            url: "cs/CheckForProcess",
            async: true,
            success: function(data) {
                if (data !== 'NotReady') {
                    $('#results').html(data);
                } else {
                    // if data not ready yet, then put up some progress
                    // and call this again in 6 seconds
                    $('#results').html('<h1>Processing...</h1>');
                    setTimeout(runIt, 6000);
                }
            }
        });
    }

    // start the first iteration
    runIt();
}
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Why the downvote? This appears to be what the OP was looking for. – jfriend00 Nov 03 '13 at 18:15
  • The use of aysnc:false is discouraged as it may block the browser. – jaredrada Nov 03 '13 at 18:16
  • @porfuse - That was just a mistake. I never meant to have that (just copied from the OP's code and didn't even see it). I changed it to `async: true` because that's what this code is written for and what I always intended. – jfriend00 Nov 03 '13 at 18:17
  • You could simply remove the property all together since async defaults to true. – jaredrada Nov 03 '13 at 18:22
  • @porfuse - yes I could, but I wanted to make sure the OP and others realize this is different from what the OP was using. I'm still wondering why there's a downvote and the OP removed their best answer. Odd. – jfriend00 Nov 03 '13 at 18:23
  • Added comments to the answer about using asynchronous ajax. – jfriend00 Nov 03 '13 at 18:27
0

The setTimeout function takes a function to execute after the timeout. You are passing an empty function. So, after 6 seconds, that empty function is executing - and obviously not doing anything.

I think you are expecting setTimeout to delay the execution of other scripts on your page. This is not the case, as setTimeout delays and executes the supplied callback function in a new thread (not blocking other execution on your page).

If you are trying to do something after 6 seconds, just supply the code inside of the function() {} code you have. Eg:

setTimeout(function() {
    $.ajax(...);
}, 6000);

or

setTimeout(runIt, 6000);

Links:
setTimeout documentation (mozilla)
Related SO question

Community
  • 1
  • 1
stephen.hanson
  • 9,014
  • 2
  • 47
  • 53