簡體   English   中英

JavaScript:setInterval()無法產生預期的輸出

[英]JavaScript: setInterval() doesn't produce expected output

請在下面查看我的代碼,我不知道為什么它會產生預期的輸出。 我認為我使用setInterval()和setTimeout的方式是錯誤的。 不知何故,該過程不會從上到下按1個順序進行。 似乎有3個線程並行運行。 我該如何解決? 謝謝。

 (function() { var nums = [1, 2, 3]; nums.forEach( (e) => { console.log(e); var frame = 0; let loop = setInterval(function() { if (frame === 3) clearInterval(loop); console.log(e + " frame " + frame); frame++; }, 1000); let wait = setTimeout(function() { console.log(e + " 2 second passed"); }, 2000); } ) })(); 

預期產量:

1
1 frame 0
1 frame 1
1 frame 2
1 2 seconds passed
2
2 frame 0
2 frame 1
2 frame 2
2 2 seconds passed
3
3 frame 0
3 frame 1
3 frame 2
3 2 seconds passed

實際輸出:

1
2
3
1 frame 0
2 frame 0
3 frame 0
1 frame 1
1 2 second passed
2 frame 1
2 2 second passed
3 frame 1
3 2 second passed
1 frame 2
2 frame 2
3 frame 2
1 frame 3
2 frame 3
3 frame 3

由於Javascript是異步的,因此您需要某種方式來等待每個間隔和超時完成,然后再運行下一個。

一種方法是使用async / await並將時間間隔和超時包裝在promise中

 (async function() { var nums = [1, 2, 3]; for (const e of nums) { console.log(e); let frame = 0; await new Promise(resolve => { let loop = setInterval(function() { if (frame === 3) { clearInterval(loop); resolve(); } else { console.log(e + " frame " + frame); frame++; } }, 100); }) await new Promise(resolve => { let wait = setTimeout(function() { console.log(e + " 2 second passed"); resolve(); }, 200); }) } })(); 

不知道您要用此代碼完成什么。 但請嘗試以下方法。 您可以控制台記錄您的要求。 做改變,如你所願,

 let nums = [1, 2, 3]; const timesecs = 1000; const timeOut = (num) => { setTimeout( () => { console.log(num); nums.forEach( (item, index) => { console.log(num + " frame " + index); } ) //console.log(`${num} ${num+1} seconds passed`); console.log(`${num} 2 seconds passed`); }, num * timesecs ) } nums.forEach((num) => { timeOut(num); }); 

JavaScript無法以這種方式工作。 您需要首先了解ASYNC操作和回調的概念。 Aysnc操作(如setTimeout和setInterval)在移動到代碼的下一行之前,不必等待其回調函數完成。 他們只是將執行光標移到下一行。 您的setInterval函數將在1000毫秒后完成其回調執行。

添加了新功能,如等待和異步功能。 您可能希望研究它們以實現所需的功能。

您正在運行的for循環應該在時間間隔內,而不是您在做什么。

 (function () { var nums = [1, 2, 3]; var ind = 0; let loop = setInterval(function(){ if(ind === 2){ clearInterval(loop); } console.log(nums[ind]); nums.forEach(e => { console.log(nums[ind] + " frame " + e); }); console.log(nums[ind] + " 2 seconds passed"); ind++; }, 2000); })(); 

您有一個forEach循環,該循環將循環3次。 在第一次迭代中,它將:

  1. console.log框架(1)
  2. 創建一個間隔,將在1秒內執行
  3. 創建將在2秒內執行的超時

然后,循環的第二次迭代將在第一次迭代之后立即發生,因此它將再次發生:

  1. console.log框架(2)
  2. 創建另一個新的第二個間隔,將在1秒內執行
  3. 創建另一個新的第二個超時,將在2秒內執行

最后,第三次迭代將立即發生,它將:

  1. console.log框架(3)
  2. 創建另一個第三個新間隔,將在1秒內執行
  3. 創建另一個新的第三次超時,將在2秒內執行

接下來,所有新創建的三個時間間隔將在循環結束后約1秒執行。 每個時間間隔將比前一個時間間隔稍稍執行。 每個變量在變量frame周圍都包含一個“封閉”(即,當它們被創建時,當將其設置為0時,它們都“捕獲”了框架,因此它們都為console.log(0)

在下一秒,這3個間隔中的每個間隔將嘗試再次運行(現在每個間隔都具有frame === 1 ),並且3個超時也將嘗試運行。 請注意,每個超時還形成了一個“關閉”,在創建e時將其值鎖定。 您最終會得到一些交錯的執行間隔,並混合執行超時。

3個超時僅一次發生一次。

輸出的其余部分是連續執行的3個間隔的集合,每個集合之間有2秒的間隔。


您只需使用一個間隔(無循環),設置為每秒觸發一次並打印一些內容,即可實現輸出。 我不確定要打印這些語句間隔多少秒的要求,因此我無法生成所需的確切代碼,但以下內容可以根據您的最佳猜測生成所需的輸出:

var num = 1;
var frame = 0;
var loop = setInterval( function() {
  if (frame === 0) {
    console.log(num);
  }
  if (frame >= 0 && frame <= 2) {
    console.log(num + " frame " + frame);
  }

  if (frame === 4) {
    console.log(num + " 2 seconds passed");
    num++;
    frame = -1;
  }
  if (num > 3) {
    clearInterval(loop);
  }
  frame++;
}, 1000);

暫無
暫無

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

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