maudulus
maudulus

Reputation: 11025

Trying to make asynchronous code run synchronously inside for loop

I have a function runSyncForLoop, in which I was hoping that the 2 second timeout would stop the openEmailPagefrom being called about 30 times in succession as linkArray is looped over. I did this based on a few other stackoverflow posts that I was reading through, one of which suggested deasync and another of which suggested sync. I think that the problem I am having is that ret is being set asynchronously, so this doesn't solve the problem. Right now, there is a pause, and then suddenly openEmailPage is fired the 30 times, although I was expecting there to be a two second delay between each fire.

function runSyncForLoop(linkArray){
    for (i in linkArray) {    
        var ret = 0 ;
        setTimeout(function(){
            openEmailPage(linkArray[i])  
        },2000); 
        ret="hello";   
    }    
    while(ret === 0) {
        require('deasync').runLoopOnce();
    }
    return ret;
}

This could would simply be the following if it didn't have the deasync/timeout stuff:

function runSyncForLoop(linkArray){
    for (i in linkArray) {    
        openEmailPage(linkArray[i])  
    }    
}

I'm trying to figure out how to run this with a two second delay between each call of openEmailPage(linkArray[i])

Upvotes: 1

Views: 635

Answers (1)

jfriend00
jfriend00

Reputation: 707158

setTimeout() is asynchronous so all it does is start a timer and your for loop just keeps on running. Thus, you end up setting 30 timers that all go off at about the same time.

Instead, you need to run your function, set a timer for two seconds and when that timer fires, run your function again. Here's one way to do that:

function runEmailLoop(linkArray) {
    var cntr = 0;

    function run() {
        if (cntr < linkArray.length) {
            openEmailPage(linkArray[cntr]);
            ++cntr;
            setTimeout(run, 2000);
        }
    }
    // run first iteration immediately, then each one two seconds after that
    run();
}

If you want the first call to openEmailPage() to wait two seconds also, you can change it like this:

function runEmailLoop(linkArray) {
    var cntr = 0;

    function run() {
        if (cntr < linkArray.length) {
            openEmailPage(linkArray[cntr]);
            ++cntr;
            setTimeout(run, 2000);
        }
    }
    // run first iteration in 2 seconds
    setTimeout(run, 2000);
}

Upvotes: 2

Related Questions