-1
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript">
        var i = 0;
        var d = 0;
        function BBB() {
            i++;
            alert("11");
            if (i <= 10)
                setTimeout("BBB()", 300);
        }
        function HHH() {
            d++;
            alert("22");
            if (d<= 10)
                setTimeout("HHH()", 300);
        }
        function CCC() {
            BBB();
            HHH();
        }
    </script>
</head>
<body>
    <input type="button" value="Submit" onclick="CCC()"/>
</body>
</html>

I would like to execute BBB function completely,then HHH function. But the result is not so.The output is 11 22 11 11......

How to solve this?Sorry for my poor english! Thanks!

3 Answers 3

1

setTimeout causes the functions to not be sequentially executed.

You would do what you do in any other asynchronous context ie

  • Pass the function names as callback names
  • Keep a global variable to keep track
  • Use events.

In your case you have a variable i keeping track of the calls & hence Like this, perhaps :

 <script type="text/javascript">
        var i = 0;
        var d = 0;
        function BBB() {
            i++;
            alert("11");
            if (i <= 10)
                setTimeout("BBB()", 300);
            else HHH();
        }
        function HHH() {
            d++;
            alert("22");
            if (d<= 10)
                setTimeout("HHH()", 300);
        }
        function CCC() {
            BBB();
        }
    </script>
Sign up to request clarification or add additional context in comments.

3 Comments

The real important fix was on CCC though
Yea, But I'm hoping OP would pay less attention to fix, & more to the problem.
@Alexander How to do?
1

Saw you tagged this with so here is a prettty elegant way to do this using the power of jQuery.

var deferredObj = $.Deferred();
var counter1 = 0;  
var counter2 = 0;  
function First() {
    counter1++;
    alert("first - " + counter1);
    if (counter1 >=3) {
        deferredObj.resolve();
        return;
    }
    setTimeout(First, 300);
}

function Second() {
    counter2++;
    alert("second - " + counter2);
    if (counter2 >= 3)
        return;
    setTimeout(Second, 300);
}

First();
deferredObj.done(function(){
    Second();
});

The key here is marking the deferred object as "resolved" when first method finish, then jQuery knows it can execute the second method. Credits for this way belong to Kevin in this answer.

Live test case.

4 Comments

@user441222, I beg to disagree. There's too much overhead going on here. Better would be something like these. The runner function receives an array of functions to execute and their order which is easily extensible. I'd probably make it an answer if OP is alive
@Alexander you are my star! Thank you!
@Alexander not really sure why not post it as answer? Looking good enough. :-)
@user441222, np, i posted it as an answer for the record :)
0

An optimized version of a function that runs a set of functions in their order.

var runner = function(fn) {
    var counter = 10, delay = 300;
    setTimeout(function run(){
        fn[0].apply(this);
        counter--;
        counter && setTimeout(run, delay);
        !counter && fn.shift() && fn.length && runner(fn);
    }, delay);
};

You can use it as follows:

var log = function(text){
    return function(){
        console.log(text);
    };
};

runner([ log("1"), log("2"), log("3") ]);

A live example.

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.