0

I was trying to create a web game but ran into trouble because of javascript's single-threaded-ness. I have a few functions like this

function printNum(currentNum, targetNum, source, delay) {
    if(currentNum < targetNum) {
        currentNum++;
        setTimeout(function() {
            for(var i=0; i<source.length; i++) {
                source[i].innerHTML = ("<p>" + currentNum + "</p>");
            }
            printNum (currentNum, targetNum, source, delay);
        },delay);
    }
}

A few functions are called at once and they proceed asynchronously because of the setTimeOut() function. But I need my code after those functions to run when they fully finish (i.e. no printNum recursion anymore). I try to avoid putting all the code later into a callback function since the game works in a while loop. I wanna create something like this

while(condition is true){
    /*some functions*/
    /*asynchronous functions*/
    /*wait till all asynchronous functions to finish*/
    /*some functions*/
}

Should I create a special class to handle them (e.g. a queue)? Or is there already framework that does the same thing? Or maybe just modify my code?

Sorry if I am not clear about my question. I am new to this language, any help is sincerely appreciated.

5
  • 1
    Maybe you can do what you want with Promises. You can't do it with a while loop, as that prevents the async procedures function running and will lock up the UI. Commented Aug 3, 2014 at 11:36
  • So let me know if I understood: you are doing something like this: while(condition) { printNum(...); } and you want to do something inside the loop right after that printNum() (when it's finished), am I right? Commented Aug 3, 2014 at 12:07
  • and the while condition - is it based on the outcome of the code within the loop? Commented Aug 3, 2014 at 12:14
  • @Barmar not sure how I can use Promise for this, I am not really familiar that, do you have any idea? @ Macro Bonelli right after printNum() yes, and @ lombausch the outcome of while does depend on the code inside the loop, but not directly on those asynchronous functions, they are intended for animation effect. Commented Aug 3, 2014 at 13:08
  • Sorry, I'm not really that familiar with using Promises, either. But if you're trying to do anything fancy with asynchronous functions, that's usually the solution. Commented Aug 3, 2014 at 13:31

2 Answers 2

1

Edit: Original code below has callback. The other control routine without callback is to use Promise/A+ and at time of writing (Aug 2014), Mozilla page says it is still experimental and not fully supported by all browsers.

Basically, promise goes like this (on FireFox):-

var p1 = new Promise(function(resolve, reject) { setTimeout(resolve, 400, "a"); });
var p2 = new Promise(function(resolve, reject) { setTimeout(resolve, 200, "b"); });
Promise.all([true, p1, p2]).then(function(values) {
  // values == [ true, 'a','b']
});

~~

Use async.js library which allows you to control the asynchronous function, minor tweak to add callback to your existing functions. Here's a code snippet:-

/* start with some synchronous functions */

/* rewrite your async functions with callback, and use async.parallel() */
async.parallel([
    function(callback){ /*asynchronous functions*/
        setTimeout(function(){
            callback(null, 'one');
        }, 200);
    },
    function(callback){ /*asynchronous functions*/
        setTimeout(function(){
            callback(null, 'two');
        }, 100);
    }
],
// optional callback
function(err, results){
    // the results array will equal ['one','two'] even though
    // the second function had a shorter timeout.
    /* continue with some synchronous functions */
});
Sign up to request clarification or add additional context in comments.

2 Comments

There are a few different asynchronous library. Here's a quick overview: Which async library should I use?
This is very very useful, I guess I have found what I need. I guess I will just take some time to figure out how to implement the library exactly to my code before I close this question.
0

Thanks to Alvin!!!I have found the solution using async.js. Have to say that it is an amazing API. However, it might be very hard to maintain. So here are the asynchronous functions:

function asychronousFn_1(callback){
     printNum(30,10,/*some source*/,200,callback);
}
function asychronousFn_2(callback){
     printNum(40,10,/*some source*/,300,callback);
}
function printNum(currentNum, targetNum, source, delay,callback) {
    if(currentNum < targetNum) {
        currentNum++;
        setTimeout(function() {
            for(var i=0; i<source.length; i++) {
                source[i].innerHTML = ("<p>" + currentNum + "</p>");
            }
            printNum (currentNum, targetNum, source, delay);
        },delay);
    }else{
         //Exiting the recursion
         callback(null,"I am continuing");
    }
}

Basically, callback method will give out a "done" signal to the async API. Then we can use the parallel function to call the functions asynchronously

function doAllAsynchronousFn(callback){//package the parallel function to another function, which can also be used by async.js
     async.parallel([
        asynchronousFn_1,
        asynchronousFn_2
    ],
    // optional callback
    function(err, results){
        //executes after everything finishes
        callback(null,"continuing");
    });
}

We can link other functions using aysnc.series()

async.series([
    doAllAsynchronousFn,/*some other functions*/],/*a callback function*/
); 

Now, functions can be linked like an electric circuits (parallels and series). Thanks again Alvin!

Hope people who are having the trouble as me find it helpful

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.