Friday, February 17, 2012

JavaScript: asynchronous function that resumes to synchronous


I have a large script that is very synchronous.



1) it runs a function like this:




var result = doSomethingSynchronous(myVar);
if (result === 'something') {
doSomethingElse();
}



the doSomethingSynchronous function has a for loop that returns a value on a if statement:




var i = 0; le = someVariable.length;
for (; i < len; i++) {
if (someVariable[i] === 'aString') {
return true;
} else {
doSomethingElse();
}
}



Because the for loop and the processing can be intense, I've replaced the for loop with an iterative queue processing function that runs itself asynchronously using setTimeout after shifting one element from the array. Once it runs asynchronously of course it doesn't return the value and assigns it to the 'result' variable in the first snippet synchronously, and the if statement there always fails. My question is, is there a way to keep this part synchronous? Have the value be assigned to result before the script goes on to the next line? Or do I necessary have to use the observer/mediator pattern or similar to notify that the asynchronous function is completed?



Alternatively I could use a callback, but the actual real code is longer than this one and all depend on synchronicity. So switching var result = doSomethingSynchronous() to asynchronous would have a domino effect on the rest of the synchronous scripts, correct? :-) This sounds like a difficult and error-prone conversion, so I thought I'd ask for advice.



Thanks!

1 comment:

  1. In order to assign the result to a value, you would need to pass through a callback and call that instead of returning a value, whether or not you're deferring functionality to a timer or not.

    function doSomething(someVariable, callback){
    var i = 0; le = someVariable.length;
    for (; i < len; i++) {
    if (someVariable[i] === 'aString') {
    callback && callback(true);
    break;
    } else {
    setTimeout(function(){ deferredSomething(callback); }, 10);
    }
    }
    }

    function deferredSomething(callback){
    /* code.. */
    callback && callback('something');
    }

    doSomething(myVar, function(result){
    if (result === 'something') {
    doSomethingElse();
    }
    });


    I'll also mention that if you are doing something intense, you should definitely look at web workers so you can offload to a background thread, especially if you're working with just a FireFox add-on. https://developer.mozilla.org/En/Using_web_workers

    ReplyDelete