繁体   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