簡體   English   中英

循環內的 setTimeout() 方法

[英]setTimeout() method inside a while loop

我已經閱讀了 w3schools 的相關頁面和其他類似問題,但似乎無法理解以下內容有什么問題:

var myfunc03 = function (i) {
  document.getElementById('d01').innerHTML += 100-i+"<br>";
};

var myFunc01 = function() {
  i=0;
  while (i<100) {
    setTimeout(myfunc03(i), 1000)
    i++;
  }
};

myFunc01(); 正在運行。

沒有任何停頓,並且 i 的所有可能值都會立即列出。

這里有邏輯錯誤嗎?

while循環不會等待setTimeout()完成。 您需要為每個設置不同的時間延遲以不同的時間執行它們並使用閉包來保存i的值。 同樣在您的情況下,函數將最初執行並且返回值設置為setTimeout()參數,因此您需要在匿名函數中調用該函數或直接設置該函數。

 var myFunc01 = function() { var i = 0; while (i < 100) { (function(i) { setTimeout(function() { document.getElementById('d01').innerHTML += 100 - i + "<br>"; }, 1000 * i) })(i++) } }; myFunc01();
 <span id="d01"></span>


雖然這里可以使用setInterval()

 var myFunc01 = function() { var i = 0; // store the interval id to clear in future var intr = setInterval(function() { document.getElementById('d01').innerHTML += 100 - i + "<br>"; // clear the interval if `i` reached 100 if (++i == 100) clearInterval(intr); }, 1000) } myFunc01();
 <span id="d01"></span>

您可以使用遞歸更簡單地做到這一點:

var i = 0;
function f1() { ... };   
function f() {
    f1();
    i += 1;
    setTimeout(function() {
        if(i < 100) {
            f();
        }
    }, 1000);
}
f();

示例

 var i = 0; var myfunc03 = function(i) { document.getElementById('d01').innerHTML += 100 - i + "<br>"; }; var myFunc01 = function() { myfunc03(i); i += 1; setTimeout(function() { if (i < 100) { myFunc01(); } }, 1000); } myFunc01();
 <div id="d01"></div>


可重用的函數

 function say(sentence) { console.log(sentence); } function sayHello() { say("Hello!"); } var fn = sayHello; var count = 10; var ms = 1000; function repeat(fn, count, ms) { var i = 0; function f() { fn(); i += 1; setTimeout(function() { if (i < count) { f(); } }, ms); } f(); } repeat(fn, count, ms);

是的。 您的代碼中有兩個問題:

  1. setTimeout函數接受一個函數作為第一個參數,但在您的代碼中, myfunc03(i)返回任何內容
  2. while 循環不能滿足您的需求,相反,您必須使用遞歸函數。 由於第二個函數應該在第一個超時觸發后調用。

示例代碼:

 var myfunc03 = function (i) { setTimeout(function() { document.getElementById('d01').innerHTML += 100-i+"<br>"; if (i < 100) { i++; myfunc03(i); } }, 1000); }; var myFunc01 = function() { myfunc03(0); }; myFunc01();
 <div id="d01"></div>

while等待setTimeout

(async () => {
  var i = 0;
  while (await new Promise(resolve => setTimeout(() => resolve(i++), 1000)) < 100) {
    console.log("I get printed 100 times every second");
  }
})();
  • 我認為您在 setTimeout 上缺少分號,您應該嘗試以以下方式傳遞參數:

     setTimeout(myfunc03, 1000*i, i);

一種簡單的選擇是改用setInterval()方法。 setInterval將每次作為循環執行代碼,直到您使用clearInterval()方法中斷它。

示例

 var index = 0; let incrementEveryHalfSecond = setInterval(function(){ index++; document.querySelector("body").innerHTML += index+'</br>'; if(index == 10) clearInterval(incrementEveryHalfSecond) }, 500)
 <body></body>

觀察您決定中斷循環,將存儲 setInterval 方法的變量作為參數傳遞到 clearInterval 方法中。 現在您可以創建函數以獲得更清晰的代碼。 w3schools 文檔

問題答案:[從 100 到 1] 我把 i 的順序倒過來簡化,但你也可以用“ 100-i ”來做。

 var myfunc03 = function (i) { document.getElementById('d01').innerHTML += i+"<br>"; }; var myFunc01 = function() { let i=100; let incrementEveryOneSecond = setInterval(function(){ myfunc03(i); if(--i == 0) clearInterval(incrementEveryOneSecond); }, 1000) }; myFunc01();
 <span id="d01"></span>

您可以創建 Timeout function 並將其與async / await一起使用

 // Timeout function const timeout = (ms) => new Promise(resolve => setTimeout(resolve, ms)); // Run some loop in async function (async () => { // Loop for 5 times for(let i = 0; i <= 5; i++) { // Do some stuff console.log(`Some stuff ${i}`); // Wait for timeout 1000 ms await timeout(1000); } })();

while 方法運行很快,並且所有超時幾乎在第一秒后執行.. 你可以做的是

  1. 而不是 while 從myfunc03調用$timeout獲取下一個值
  2. 在你的 while 調用超時中,增加秒數,如i*1000

此外,正如其他人指出的那樣,您不能使用像setTimeout這樣的參數調用函數,請使用匿名函數,例如

...
while (i<100) {
  setTimeout(
     function(i){
        myfunc03(i);
     }, i*1000);
   i++;
}
...

為此

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM