以下是jsfiddle上的代码
<script>
function updateSync1() {
for (var i = 0; i < 1000; i++) {
document.getElementById('output').innerHTML = i;
}
}
function updateSync2() {
for (var i = 0; i < 1000; i++) {
setTimeout(document.getElementById('output').innerHTML = i, 0);
}
}
function updateAsync() {
var i = 0;
function updateLater() {
document.getElementById('output').innerHTML = (i++);
if (i < 1000) {
setTimeout(updateLater, 0);
}
}
updateLater();
}
</script>
<div class="row btn_area">
<button class="btn btn-info" onclick="updateSync1()">Run Sync 1</button>
<button class="btn btn-info" onclick="updateSync2()">Run Sync 2</button>
<button class="btn btn-info" onclick="updateAsync()">Run Async</button>
<span class="label label-info pull-right" style="display:block;" id="output"></span>
</div>
http://jsfiddle.net/himaneasy/y1534ths/
当我点击“运行同步1”时,代码将直接运行到999.
当我点击“运行同步2”时,代码将直接运行到999.
当我点击“运行异步”时,页面将逐一呈现。
任何人都可以帮助解释Run Sync1&amp;运行Sync2? 为什么运行同步2中的setTimeout不能逐个渲染? 谢谢!
答案 0 :(得分:6)
Javascript执行是single-threaded。它使用任务队列和堆栈来执行东西。
这段代码:
for (var i=0;i<length;i++) {
setTimeout(drawChartFunc,0);
}
将在任务队列上添加[length] setTimeouts
次调用并随后执行所有这些调用(0 ms超时)。只有最后一个操作才会更新屏幕,因为所有超时任务都首先出现在堆栈上(在循环之后,任务队列包含[length] setTimeout
次调用)。每个超时都执行drawChartFunc
。现在drawChartFunc
确实在任务队列上放置了一个屏幕更新功能,但剩下的超时时间先到,所以首先执行下一个超时 - 屏幕更新功能只能在后执行 length setTimeout
调用已完成(取自任务队列/堆栈)。这也是随后完成的,但速度非常快。如果您的眼睛经过训练可以看到纳秒转换,您可能已经在输出中发现了后续数字;)
现在
function updateLater() {
drawChartFunc();
i++;
if (i < length) {
setTimeout(updateLater, 0);
}
}
首先运行drawChartFunc
将屏幕更新放在任务队列上,然后将增量i
放在任务队列上,并且 - 如果适用 - 之后向任务添加新的setTimeout
队列。换句话说,drawChartFunc
放在堆栈上,将屏幕更新放在堆栈上,两者都执行,随后超时放在堆栈上,放置{{1}在堆栈上......等等。
确认javascript任务队列/堆栈:this video对我来说非常有用。
这是你的jsFiddle,重写了一下。它显示了两种方法的排队过程。
答案 1 :(得分:0)
setTimeout(callback, interval)
有两个参数:一个回调函数,以及执行它的时间间隔。 interval
参数确定执行callback
的时间:在您的情况下,0毫秒,即尽快执行。
在您的代码中:
function updateSync2() {
for (var i = 0; i < 1000; i++) {
setTimeout(document.getElementById('output').innerHTML = i, 0);
}
}
您已创建了1000个setTimeout
函数,这些函数都会尽快执行。