使用setTimeout递归调用函数

时间:2014-08-27 11:12:34

标签: javascript

我希望用setTimeout递归调用几个函数。

var flag = 0 ;
function slave1(){
    if(flag < 60) {
        var COPY_PO_LINE_DIV = document.getElementById("DOM_ELEMENT1"); // Checking if DOM has loaded or not. If yes then doing something.
        if (COPY_PO_LINE_DIV != null) {
            flag = 0;
            //doing something
        } else { 
            setTimeout(slave1,2000); //waiting for 2 seconds and checking again.
        }
    }
}

//doing similar task
function slave2(){
    if(flag < 60) {
        var COPY_PO_LINE_DIV = document.getElementById("DOM_ELEMENT2");              
        if (COPY_PO_LINE_DIV != null) {
            flag = 0;
            //doing something
        } else {
            setTimeout(slave2,2000);
        }
    }
}

function master() {
    slave1();
    console.log("Without completing slave1 function.");
    slave2();
}

通过master()函数,我希望一个接一个地调用多个函数,但是在当前情况下,它调用slave2()而不完成slave1()。如何确保slave1()已执行完毕。如果没有加载DOM元素,那么它应该每2秒执行60次,而不应该从slave1()出来并转到下一个。

如果没有加载dom元素而没有将控件返回到下一个函数,我想执行相同的函数60次。

4 个答案:

答案 0 :(得分:3)

您需要调整slave1以在完成后运行回调slave2

function slave1(callback){
    if(flag < 60) {
        var COPY_PO_LINE_DIV = document.getElementById("DOM_ELEMENT1"); // Checking if DOM has loaded or not. If yes then doing something.
        if (COPY_PO_LINE_DIV != null) {
            flag = 0;
            //doing something
            callback();
        } else { 
            setTimeout(slave1,2000); //waiting for 2 seconds and checking again.
        }
    }
}

function slave2(){...}

function master() {
    slave1(slave2);
    console.log("Without completing slave1 function.");
}

这是你的基本javascript链接。如果你有更多的奴隶你可能想要调查async.series,否则你会进入回调地狱,因为Gabs00说得很好:

slave1(function(){
    slave2(function(){
        slave3(function(){
            slave4(slave5);
        });
    });
});

如果需要将值传递给回调,则需要使用中间匿名函数,该函数依次使用相关参数调用预期的回调。为此,您需要定义函数,以便它们使用参数:

function slave1(str, callback){...}
function slave3(i, callback){...}

slave1("some argument", function(){
    slave2("another argument", function(){
        slave3(1, function(){
            slave4(2, slave5);
        });
    });
});

答案 1 :(得分:1)

考虑将承诺用于此类事情。这里是jQuery之上的一个实现,其他promise库的工作方式类似。

function waitForElement(elementId, maxTries, checkInterval) {
    var d = $.Deferred(), intvalID, checkFunc;

    // set up default values
    maxTries = maxTries || 60;
    checkInterval = checkInterval || 2000;

    checkFunc = function () {
        var elem = document.getElementById(elementId);
        if (maxTries-- > 0 && elem) {
            clearInterval(intvalID);
            d.resolve(elem);
        }
        if (maxTries <= 0) {
            clearInterval(intvalID);
            d.reject(elementId);
        }
    };

    // set up periodic check & do first check right-away
    intvalID = setInterval(checkFunc, checkInterval);
    checkFunc();

    return d.promise();
}

现在,如果您想逐个测试元素,可以像这样级联调用:

function master() {
    waitForElement("DOM_ELEMENT1").done(function (elem1) {
        waitForElement("DOM_ELEMENT2").done(function (elem2) {
            alert("elem1 and elem2 exist!");
            // now do something with elem1 and elem2
        }).fail(function () {
            alert("elem1 exists, but elem2 was not found.");
        });
    }).fail(function () {
        alert("elem1 not found.");
    });
}

或者您可以并行执行此操作并在所有元素都存在时调用回调:

function master() {
    $.when(
        waitForElement("DOM_ELEMENT1"),
        waitForElement("DOM_ELEMENT2")
    )
    .done(function (elem1, elem2) {
        alert("elem1 and elem2 exist!");
        // now do something with elem1 and elem2 
    })
    .fail(function () {
        alert("not all elements were found before the timeout");
    });
}

答案 2 :(得分:0)

您的slave2函数应作为回调传递给slave1函数,并应在slave1完成后调用(如果有的话)。您当前的情况很常见,因为setTimeout()函数是异步的,因此JS解释器不会等到函数完成,而是在Evet循环结束时设置setTimeout()结果并继续处理master()方法。

答案 3 :(得分:0)

为了将参数传递给函数,创建匿名函数结果证明是一种矫枉过正。请考虑使用“绑定”。所以,如果你有

function slave1(str, callback){...}
function slave2(str, callback){...}
function slave3(i, callback){...}
function slave4(i, callback){...}
function slave5()

而不是使用

slave1("some argument", function(){
    slave2("another argument", function(){
        slave3(1, function(){
            slave4(2, slave5);
        });
    });
});

考虑使用

slave1("some argument", 
    slave2.bind(null, "another argument",
        slave3.bind(null, 1,
            slave4.bind(null, 2, slave5)
        )
    )
);

在内存和CPU利用率方面更容易,更高效。 现在,如何使用setTimeout执行此操作:

slave1("some argument",
    setTimeout.bind(null, slave2.bind(null, "another argument",
        setTimeout.bind(null, slave3.bind(null, 1,
            setTimeout.bind(null, slave4.bind(null, 2,
                setTimeout.bind(null, slave5, 0)
            ),0)
        ),0)
    ),0)
);

我在更详细地解释了这个问题 http://morethanslightly.com/index.php/2014/09/executables-the-standard-solution-aka-mind-the-bind/