理解setTimeout

时间:2018-06-15 22:30:15

标签: javascript

我一直试图让一系列句子出现在前一个句子后2秒,使用setTimeout显示每个句子,并使用setInterval重复此过程一定次数(由用户定义)。 / p>

以下示例代码显示了我的理解位置以及我感到困惑的地方:



	var myComments = document.getElementById("comments");
	var subtractor = 5;
	var timer, myRun;
	
	window.onload = onStart();
	
	function onStart() {
		alert("First Comment");
		myRun = setInterval(function() {
			alert("Sub = " + subtractor);
			setTimer("<p>This is a first sentence. Subtractor = " + subtractor + "</p>");
			setTimer("<p>This is a second sentence. Subtractor = " + subtractor + "</p>");
			setTimer("<p>This is a third sentence. Subtractor = " + subtractor + "</p>");
			subtractor = subtractor - 1;
			if (subtractor < 1) {
				alert("Subtractor to clear");
				clearInterval(myRun);
				}
		}, 2000);
		alert("Last Comment");
	}
	
	function setTimer(setText) {
		clearTimeout(timer);
		timer = setTimeout(function() {myComments.innerHTML = myComments.innerHTML + setText;}, 2000);
	}
&#13;
<div id="comments"></div>
&#13;
&#13;
&#13;

警报只是作为测试点,并显示我缺乏理解:

  • 为什么在第一个警报之后立即显示最后一个警报,然后在setInterval中显示警报? - 因为setTimeout是异步的!
  • 除了生成的最后一句话之外,为什么没有显示任何句子? - 由于它们是异步的,下一个计时器会取消前一个计时器,只留下最后一个计时器。
  • 我哪里错了?如何让句子一个接一个地出现,每个句子之间有两秒钟的延迟?我是否将每个计时器嵌套在之前的?

对不起,最后一个问题更多是我自己的想法;试试!

2 个答案:

答案 0 :(得分:1)

  

为什么在第一个警报之后立即显示最后一个警报,然后在setInterval内显示警报?

最后一个警报不在setTimeout或setInterval内,因此立即触发。其他人都在2000ms的setTimeout内,所以两秒钟之后就会开火(一次全部开火)。

  

除了生成的最后一句话之外,为什么没有显示任何句子?

你以相同的2000毫秒延迟同时发射三个setTimeouts,因此所有三个都在两秒钟之后几乎同时发射。它们内部的clearTimeout相互碰撞(因为你重复使用相同的timer变量来跟踪它们),这阻止了它们中的两个被激活。

  

我哪里错了?

您对setTimer的每次调用都应使用不同的时间延迟,这样他们就不会同时触发所有内容。同时,setInterval应该具有足够长的间隔,因此在它设置的三个setTimeout完成之前它不会循环。无需在setTimout调用上调用clearTimeout;默认情况下,他们会运行一次然后停止,这就是你想要的。您需要的唯一地方是停止setInterval。

您可能还想立即触发第一次迭代,因此它会立即开始,而不是等待第一个间隔完成:

&#13;
&#13;
var myComments = document.getElementById("comments");
var subtractor = 5;
var timer, myRun;

window.onload = onStart();

function setTimers() {
  //alert("Sub = " + subtractor);
  setTimer("<p>This is a first sentence. Subtractor = " + subtractor + "</p>", 0); // no delay
  setTimer("<p>This is a second sentence. Subtractor = " + subtractor + "</p>", 2000); // 2s delay
  setTimer("<p>This is a third sentence. Subtractor = " + subtractor + "</p>", 4000); // 4s delay
  subtractor = subtractor - 1;
  if (subtractor < 1) {
    //alert("Subtractor to clear");
    clearInterval(myRun);
  }
}

function onStart() {
  //alert("First Comment");
  myRun = setInterval(setTimers, 6000); // 6 seconds for the full interval
  setTimers(); // so you don't have to wait 6 seconds for the first run
}

function setTimer(setText, delay) {
  timer = setTimeout(function() {
    myComments.innerHTML = myComments.innerHTML + setText;
  }, delay);
}
&#13;
<div id="comments"></div>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

看到另一个答案解释了问题,我只会回答“我将如何实现我想要的”评论 - 从最现代(和最干净的代码)方式开始

var myComments = document.getElementById("comments");
var delay = timeout => new Promise(resolve => setTimeout(resolve, timeout));
var subtractor = 5;

window.onload = onStart();

async function onStart() {
    for (let i = subtractor; i > 0; --i) {
        await setTimer("<p>This is a first sentence. Subtractor = " + i + "</p>");
        await setTimer("<p>This is a second sentence. Subtractor = " + i + "</p>");
        await setTimer("<p>This is a third sentence. Subtractor = " + i + "</p>");
    }
}

async function setTimer(setText) {
    await delay(2000);
    myComments.innerHTML = myComments.innerHTML + setText;
}
<div id="comments"></div>

现在承诺链接基本上只是简化了回调金字塔

var myComments = document.getElementById("comments");
var delay = timeout => new Promise(resolve => setTimeout(resolve, timeout));
var subtractor = 5;

window.onload = onStart();

function onStart() {
    let p = Promise.resolve();
    for (let i = subtractor; i > 0; --i) {
        p = p.then (() => setTimer("<p>This is a first sentence. Subtractor = " + i + "</p>"));
        p = p.then (() => setTimer("<p>This is a second sentence. Subtractor = " + i + "</p>"));
        p = p.then (() => setTimer("<p>This is a third sentence. Subtractor = " + i + "</p>"));
    }
}

function setTimer(setText) {
    return delay(2000).then(() => {
        myComments.innerHTML = myComments.innerHTML + setText;
    });
}
<div id="comments"></div>

现在,旧学校的回调链接 - 你可以在这一个中看到厄运形成的金字塔!

var myComments = document.getElementById("comments");
var subtractor = 5;

window.onload = onStart();

function onStart() {
    setTimer("<p>This is a first sentence. Subtractor = " + subtractor + "</p>", function() {;
        setTimer("<p>This is a second sentence. Subtractor = " + subtractor + "</p>", function() {
            setTimer("<p>This is a third sentence. Subtractor = " + subtractor + "</p>", function() {
                subtractor = subtractor - 1;
                if (subtractor > 0) {
                    onStart();
                }
            })
        });
    });
}

function setTimer(setText, cb) {
    setTimeout(function() {
        myComments.innerHTML = myComments.innerHTML + setText;
        cb();
    }, 2000);
}
<div id="comments"></div>

我不会理解用“不断增加的超时值”做你想要的最简单的方法,因为已经显示了