Prostak Prostak - 5 months ago 11
Javascript Question

How to do a "for" loop with asynchronous condition in Javascript?

I have this function:

waitForFreeAccnt.prototype.isMemberFree = function () {
var self = this;

self.api.getMemberInfo(function () {
var accType = self.api.connect.accountType;
console.log(accType);
if (accType === 'FREE') {
console.log('it is free');
return true;
} else {
console.log('it is not free');
return false;
}
});
};


I would like to wait till the account is free for up to 10 seconds with something like that:

var test = function () {
for (var start = 1; start < 10; start++) {
var result = self.isMemberFree();
console.log(result);
if (result) {
break;
} else {
self.api.pause(1000);
console.log('waiting');
}
}
};


But it doesn't work because
self.api.getMemberInfo
is asynch call. This is super frustrating with Javascript. Any other language it would be so simple to do. How do I force the for loop to wait for
self.isMemberFree()
to finish executing before proceeding with the loop?

Also to note, this is not in browser execution so I don't care about anything hanging.

Answer

I don't have my work laptop today because it is Sunday, I'm coding this on sublime. Apologise if the syntax is a bit off.

To solve your problem I would recommend changing isMemberFree() to take in a callback function. This is because isMemberFree is async, and you will need a way to report the result after it has done the work.

Then change test function to use setTimeout API to wait a second. Wrap the function call for isMemberFree() to be in a nested function and call it recursively, that way you'll have synchronize control over the async calls.

Look at the coding example:

waitForFreeAccnt.prototype.isMemberFree = function (done) {
    var self = this;

    self.api.getMemberInfo(function () {
        var accType = self.api.connect.accountType;
        console.log(accType);
        if (accType === 'FREE') {
            console.log('it is free');
            return done(null, true);
        } else {
            console.log('it is not free');
            return done(null, false);
        }
    });
};


var test = function () {

    var testMembership = function(waitAttempt, isFree) {
        if (isFree) { 
            return; 
        }
        else if (waitAttempt > 10) {
            // wait exceeded, do something.
            return;
        }
        setTimeout(function() {
            self.isMemberFree(function(err, isFree) {
                testMembership(waitAttempt+=1, isFree);
            });
        }, /*total milliseconds in 1sec=*/1000);
    }

    testMembership(/*WaitAttempts=*/0, /*isFree=*/false);
};

What the above code does is that, presumably something has already been done to the member's account and now test function is called. So it waits for 1 second, then call isMemberFree function, this happens recursively until either isMemberFree() returns true OR the 10 seconds wait has been exceeded.

Comments