Javascript 具有相同间隔的多个setTimeout()函数的执行顺序
考虑以下Javascript代码:Javascript 具有相同间隔的多个setTimeout()函数的执行顺序,javascript,Javascript,考虑以下Javascript代码: function(){ setTimeout(function() { $("#output").append(" one "); }, 1000); setTimeout(function() { $("#output").append(" two "); }, 1000); } 您还可以在上看到此示例 我是否可以确保#output的值始终是“一二”,按该顺序排列?通常,我会这样处理这个问题:
function(){
setTimeout(function() {
$("#output").append(" one ");
}, 1000);
setTimeout(function() {
$("#output").append(" two ");
}, 1000);
}
您还可以在上看到此示例
我是否可以确保#output
的值始终是“一二”
,按该顺序排列?通常,我会这样处理这个问题:
function(){
setTimeout(function() {
$("#output").append(" one ");
$("#output").append(" two ");
}, 1000));
}
但我不能这样做,因为我从一个服务器收到消息,它告诉我要执行哪个函数(在本例中是append“one”
或append“two”
),我必须稍微延迟执行
我已经在Internet Explorer 9、Firefox 14、Chrome 20和Opera 12中测试过这段代码,输出总是“一二”
,但我能确定这会一直是这样吗?不,你不能确定。它是异步的
但事实上,这可能是真的,因为该机制在浏览器中实现了。是的,输出将始终是
“一二”
因为第一个
setTimeout
总是在第二个setTimeout
之前运行,如果它们具有相同的延迟时间,那么第一个的回调函数总是在第二个的回调函数之前执行。是,因为javascript代码在一个线程中执行,所有异步事件,像单击
,鼠标移动
,都排队执行。当您调用setTimeout
时,引擎将在其队列中插入一个计时器,以便将来执行,至少在delay
时间之后执行。因此,两个setTimeout
会一个接一个地生成两个计时器
你可以看看约翰·雷斯格的作品。在你的小提琴里摆弄一下
$(document).ready(function() {
setTimeout(function() {
$("#output").append(" one ");
}, 1000);
});
$(document).ready(function() {
setTimeout(function() {
$("#output").append(" two ");
}, 999);
});
你会看到这两者
output: one two
output: two one
这是可能的。所以Speransky是对的,你不能总是依赖于你的超时以相同的顺序执行
注意,我用1ms更改了一次,以显示在999ms超时之前可以执行1000ms超时
编辑:下面的代码可以延迟执行,而不会在one
之前打印two
function(){
setTimeout(function() {
$("#output").append(" one ");
setTimeout(function() {
$("#output").append(" two ");
}, 100);
}, 1000);
}
更新
我已经用这个方法更新了你的小提琴 这个方法怎么样--从您的服务器获取一个要做的事情的列表--
通过这种方式,您可以决定顺序。如果事件是同步的,则有
Continuum
函数按顺序运行函数:
function keyedSequence(key, fn) {
fn = fn || this;
key.push({fn:fn});
return function() {
for(var i=0, n, full=1; i<key.length; i++) {
n = key[i];
if(n.fn == fn) {
if(!n.called) n.called = 1, n.args = key.slice.call(arguments);
if(!full) break
}
if(!n.called) full = 0
}
if(full) for(i=0; i<key.length; i++)
n = key[i], key[i] = {fn:n.fn}, n.fn.apply(n, n.args);
}
}
Function.prototype.seq = keyedSequence;
单击test2
,然后单击test1
,执行顺序仍然是function1
然后是function2
另一种说法是:
window.onload = function() {
var key = [];
document.getElementById("test1").addEventListener('click', keyedSequence(key, function1), false);
document.getElementById("test2").addEventListener('click', keyedSequence(key, function2), false);
}
规格是
我对第7.3节中setTimeout
步骤8的解释是执行顺序应该得到保证
然而,我调查了这个问题,因为当窗口在Chrome中最小化然后最大化时,我发现来自外部源(如WebSocket或webworkers)的事件中设置的超时以错误的顺序执行。我假设这是一个浏览器错误,希望很快就能修复。这取决于浏览器,因为setTimout是浏览器中窗口对象的一部分,而不是在ECMAScript中定义的。根据规范,应该订购具有相同任务源的内容。所以是的 您需要延迟执行的原因是什么?在这里您可以找到HTML5中的计时器规范:一种解决方案是延迟计时器本身。我已经提出了一个可能的解决方案如果你关心执行顺序,你可能想看看这个页面@SperanskyDanil的可能重复,即使差异小于1ms,但顺序是固定的。这不是所问的op,在他的问题中,
setTimeout
的执行顺序是固定的,如果插入第一个计时器的时间超过1ms,则结果是“一拖”
。但是如果不到1ms,结果是“两个一”
。我在不同的浏览器中使用过这个,但我总是得到结果“两个一”
,可能是因为我有一台相当快的电脑;)我可以想象,在其他PC上,顺序可能不同,但我总是使用相同的时间间隔(如果我无法确保问题中所问的执行顺序,我必须寻找另一种解决方案)。请查看上述注释中的链接,这些注释来自一些
,请参见,此API不能保证计时器完全按计划运行。CPU负载、其他任务等可能会导致延迟。
第9点关于用户代理时间。即使javascript在单个线程上执行,其行为也可能与您预期的不同。我使用Chrome 20.0.1132.57 m进行测试。可能您正在使用不同的浏览器。当我们使用这段代码时,它会执行不同的操作。如果你依赖执行命令,那是非常危险的!我认为不能保证。。完全按计划
意味着设置超时(func,1000)
计时器不能保证在1000毫秒后执行。这并不能回答我原来的问题。我只是想解释为什么我不能使用我在问题中提出的第二种方法。如果我不能以相同的时间间隔使用setTimeout()确保执行顺序,我必须寻找另一个适合我的应用程序的解决方案。但是我不能使用第二个解决方案。感谢您指向规范!根据您的经验,您可以告诉我不要依赖于此。我无法在提供的链接中找到第7.3节?内容改变了吗?此外,我还附加了以下内容:“此API不能保证计时器完全按计划运行。CPU负载、其他任务等导致的延迟是意料之中的。”是的,现在已经过了相当长的一段时间,规范文档也发生了更改。问题不在于计时器是否完全按计划启动,而在于它们是否按预期顺序启动,即使有延迟。我相信,由于Javascript的“转向”特性,WebSocket或webworkers将执行
window.onload = function() {
var key = [];
document.getElementById("test1").addEventListener('click', function1.seq(key), false);
document.getElementById("test2").addEventListener('click', function2.seq(key), false);
}
window.onload = function() {
var key = [];
document.getElementById("test1").addEventListener('click', keyedSequence(key, function1), false);
document.getElementById("test2").addEventListener('click', keyedSequence(key, function2), false);
}