[英]Calling a function recursively with setTimeout
我想用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次相同的功能。
您需要調整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);
});
});
});
考慮對此類事情使用諾言。 在此基於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");
});
}
您的slave2
函數應作為回調傳遞給slave1
函數,並應在它完成后在slave1
調用(如果有的話?)。 您的當前情況非常普遍,因為setTimeout()
函數是異步的,因此JS解釋器不會等到函數完成后才在Evet循環的末尾設置setTimeout()
結果並繼續處理master()方法。
為了將參數傳遞給函數,創建匿名函數實在是太過分了。 考慮改為使用“綁定”。 所以,如果你有
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/上更詳細地解釋了該問題
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.