3

Having a nightmare with a function that's finishing before all the code has run. Am trying to build in a counter, and only returning when the code is finished.

I've emulated this like so (I know it's not fantastic, but if someone could point me along the right lines, I'd be very grateful):

//I want this to alert "Done"
alert(timerCheck());

function timerCheck() {
    var finished;
    var myLoop = 5;
    for (i = 0; i < myLoop; i++) {
        //This is emulating the slow code
        window.setTimeout(checkFinished, 900);
        alert(i);
    }
    function checkFinished() {
        //I originally had the "return here, before realising my error
        finished = true;
    }
    if (finished) {
        //This is where my problem is 
        return "done";
    }
}

Like I said, a much simplified example - if someone could point out the mistake, it'd save me a lot of hassle!

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Richard
  • 1,148
  • 3
  • 18
  • 33
  • 5
    You cannot get the return value of a function synchronously if that function calls and depends on asynchronous functions. You have to work with callbacks. See http://stackoverflow.com/questions/2070275/javascript-closures-and-callbacks – Felix Kling May 24 '12 at 15:02
  • if you have access to jquery, you can use deferred and promise: http://stackoverflow.com/questions/5009194/how-to-use-jquery-deferred-with-custom-events – jbabey May 24 '12 at 15:02

3 Answers3

4

You cannot get the return value of a function synchronously if that function calls and depends on asynchronous functions.

You have to work with callbacks. See this question for some more details.

For example, your function would look like this:

// pass a callback which gets the result of function
timerCheck(function(result) {
    alert(result);
});

function timerCheck(callback) {
    var myLoop = 5,
        j = 0;

    for (var i = 0; i < myLoop; i++) {
        // This is emulating the slow code
        // this will invoke `checkFinished` immediately, 
        // after 900ms, after 1800ms, after 2700ms and after 3600ms
        window.setTimeout(checkFinished, i * 900);
    }

    function checkFinished() {
       j++;
       // after checkFinish was called 5 times, we invoke the callback
       if(j === 5) {
           callback('done');
       }
    }
}
Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
0

As FelixKling commented, you cannot get the return value of a function synchronously if that function calls and depends on asynchronous functions. One solution of those kind of jobs could be:

var finished = false;

function mySlowCode() {
    setTimeout(function() {
        finished = true;
    }, 1000);
}

function timerCheck() {
    // legend...
    (function waitForIt() {
        setTimeout(function() {
            if (!finished) {
                waitForIt();
            } else {
                // dary!
                letsDoIt();
            }
        }, 10);
    })();
}

function letsDoIt() {
    alert("done");
}

mySlowCode();
timerCheck();

The function timerCheck() will call the function letsDoIt() once the function mySlowCode() is finished.

sp00m
  • 47,968
  • 31
  • 142
  • 252
-3

Have you tried it with no parens after function name?

alert(timerCheck);
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
kylehyde215
  • 1,216
  • 1
  • 11
  • 18