首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解setTimeout

理解setTimeout
EN

Stack Overflow用户
提问于 2018-06-15 22:30:15
回答 2查看 62关注 0票数 0

我一直试图让一系列句子在上一个句子之后2秒出现,使用setTimeout显示每个句子,并使用setInterval重复这个过程一定的次数(如用户定义的)。

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

代码语言:javascript
复制
	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);
	}
代码语言:javascript
复制
<div id="comments"></div>

警报只是作为测试点存在,表明我缺乏理解:

  • 为什么在第一个警报之后立即显示最后一个警报,然后显示来自setInterval内部的警报?-因为setTimeout是异步的!
  • 除了生成的最后一句之外,为什么所有的句子都不显示?--因为它们是异步的,所以下一个定时器取消了前一个,只剩下最后一个要显示。
  • 我哪里出问题了?我如何使句子一个接一个地出现,每句话之间都有两秒钟的延迟?我是否在前一个定时器中嵌套每个计时器?

对不起,最后一个问题更多的是在我自己的脑子里;去考试吧!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-06-15 22:40:02

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

最后一个警报不在setTimeout或setInterval中,因此立即触发。其他的都在2000毫秒的setTimeout中,所以两秒钟后就可以启动了(全部一次)。

除了最后一句之外,为什么所有的句子都没有显示出来?

你用同样2000毫秒的延迟同时发射三个setTimeouts,所以它们几乎在两秒钟后同时发射。它们内部的clearTimeouts正在相互碰撞(因为您重用相同的timer变量来跟踪它们),这就阻止了其中的两个触发。

我哪里出问题了?

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

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

代码语言:javascript
复制
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);
}
代码语言:javascript
复制
<div id="comments"></div>

票数 1
EN

Stack Overflow用户

发布于 2018-06-15 22:58:37

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

代码语言:javascript
复制
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;
}
代码语言:javascript
复制
<div id="comments"></div>

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

代码语言:javascript
复制
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;
    });
}
代码语言:javascript
复制
<div id="comments"></div>

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

代码语言:javascript
复制
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);
}
代码语言:javascript
复制
<div id="comments"></div>

我不会用“永远增加超时值”的最简单的方式来做你想做的事情,因为这已经显示出来了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50883394

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档