我希望用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次。
答案 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/