关于javascript setTimeout异步模式

时间:2014-01-01 08:41:02

标签: javascript jquery

<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>

我想完全执行BBB功能,然后是HHH功能。 但结果并非如此。输出为11 22 11 11......

如何解决这个问题?抱歉我的英语不好!谢谢!

3 个答案:

答案 0 :(得分:2)

setTimeout导致函数不能顺序执行。

您可以在任何其他异步上下文中执行操作,即

  • 将函数名称作为回调名称
  • 传递
  • 保留一个全局变量以跟踪
  • 使用活动。

在你的情况下,你有一个变量 i 跟踪电话&amp;因此,或许这样:

 <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>

答案 1 :(得分:1)

看到你用标记了这一点,所以这是一种优雅的方法,可以使用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();
});

这里的关键是在第一个方法完成时将延迟对象标记为“已解析”,然后jQuery知道它可以执行第二个方法。这种方式的积分属于凯文this answer

Live test case

答案 2 :(得分:1)

一个函数的优化版本,它按顺序运行一组函数。

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);
};

您可以按如下方式使用它:

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

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

A live example.