Javascript setTimeout存在0延迟问题
我注意到一个奇怪的行为:如果我有一系列任务,并且希望延迟它们的执行,那么我可以使用setTimeout,每个任务都延迟0。 (见附件) 一切都很完美:任务排队并尽快执行 但是。。。如果各种setTimeout的调用非常接近,那么我发现有时候(很少发生!)没有按照正确的顺序执行。Javascript setTimeout存在0延迟问题,javascript,settimeout,Javascript,Settimeout,我注意到一个奇怪的行为:如果我有一系列任务,并且希望延迟它们的执行,那么我可以使用setTimeout,每个任务都延迟0。 (见附件) 一切都很完美:任务排队并尽快执行 但是。。。如果各种setTimeout的调用非常接近,那么我发现有时候(很少发生!)没有按照正确的顺序执行。 为什么?从来没有人承诺过他们会按照“正确”的顺序被解雇(具有相同超时的任务将按照设置为超时的顺序执行)设置超时仅保证: 每个超时只执行一次(除非页面同时消失) 每个超时执行的时间都不早于应该执行的时间 没有关于执行命
为什么?从来没有人承诺过他们会按照“正确”的顺序被解雇(具有相同超时的任务将按照设置为超时的顺序执行)<代码>设置超时仅保证:
- 每个超时只执行一次(除非页面同时消失)
- 每个超时执行的时间都不早于应该执行的时间
var defer = (function(){
//wrapped in IIFE to provide a scope for deferreds and wrap
var running = false;
var deferreds = [];
function wrap(func){
return function(){
func();
var next = deferreds.shift();
if(next){
setTimeout(wrap(next),0);
}else{
running = false;
}
}
}
return function(func){
if(running){
deferreds.push(func);
}else{
setTimeout(wrap(func),0);
running = true;
}
}
})()
演示:从来没有人承诺过他们会按照“正确”的顺序被解雇(具有相同超时的任务将按照设置为超时的顺序执行)<代码>设置超时仅保证:
- 每个超时只执行一次(除非页面同时消失)
- 每个超时执行的时间都不早于应该执行的时间
var defer = (function(){
//wrapped in IIFE to provide a scope for deferreds and wrap
var running = false;
var deferreds = [];
function wrap(func){
return function(){
func();
var next = deferreds.shift();
if(next){
setTimeout(wrap(next),0);
}else{
running = false;
}
}
}
return function(func){
if(running){
deferreds.push(func);
}else{
setTimeout(wrap(func),0);
running = true;
}
}
})()
演示:HTML5草案规范声明setTimeout方法可以异步运行(这意味着回调的执行顺序可能不会保留),这可能是您的浏览器正在执行的操作 … 六,。返回句柄,然后继续异步运行此算法 七,。如果方法上下文是一个窗口对象,请等待与方法上下文关联的文档完全处于活动状态,并等待更长的超时毫秒(不一定连续) 在任何情况下,人们都可以通过做类似的事情来解决这个问题:
function inOrderTimeout(/* func1[, func2, func3, ...funcN], timeout */)
{ var timer; // for timeout later
var args = arguments; // allow parent function arguments to be accessed by nested functions
var numToRun = args.length - 1; // number of functions passed
if (numToRun < 1) return; // damm, nothing to run
var currentFunc = 0; // index counter
var timeout = args[numToRun]; // timeout should be straight after the last function argument
(function caller(func, timeout) // name so that recursion is possible
{ if (currentFunc > numToRun - 1)
{ // last one, let's finish off
clearTimeout(timer);
return;
}
timer = setTimeout(function ()
{ func(); // calls the current function
++currentFunc; // sets the next function to be called
caller(args[currentFunc], timeout);
}, Math.floor(timeout));
}(args[currentFunc], timeout)); // pass in the timeout and the first function to run
}
函数inOrderTimeout(/*func1[,func2,func3,…funcN],超时*/)
{var timer;//用于稍后超时
var args=arguments;//允许嵌套函数访问父函数参数
var numToRun=args.length-1;//传递的函数数
如果(numToRun<1)返回;//damm,则不运行任何内容
var currentFunc=0;//索引计数器
var timeout=args[numToRun];//超时应该在最后一个函数参数之后
(函数调用方(func,timeout)//name以便可以递归
{if(currentFunc>numToRun-1)
{//最后一个,我们结束吧
清除超时(计时器);
返回;
}
定时器=设置超时(函数()
{func();//调用当前函数
++currentFunc;//设置要调用的下一个函数
调用者(args[currentFunc],超时);
},数学地板(超时);
}(args[currentFunc],timeout));//传入超时和要运行的第一个函数
}
HTML5草案规范声明setTimeout方法可以异步运行(这意味着回调的执行顺序可能不会保留),这可能是您的浏览器正在执行的操作
…
六,。返回句柄,然后继续异步运行此算法
七,。如果方法上下文是一个窗口对象,请等待与方法上下文关联的文档完全处于活动状态,并等待更长的超时毫秒(不一定连续)
在任何情况下,人们都可以通过做类似的事情来解决这个问题:
function inOrderTimeout(/* func1[, func2, func3, ...funcN], timeout */)
{ var timer; // for timeout later
var args = arguments; // allow parent function arguments to be accessed by nested functions
var numToRun = args.length - 1; // number of functions passed
if (numToRun < 1) return; // damm, nothing to run
var currentFunc = 0; // index counter
var timeout = args[numToRun]; // timeout should be straight after the last function argument
(function caller(func, timeout) // name so that recursion is possible
{ if (currentFunc > numToRun - 1)
{ // last one, let's finish off
clearTimeout(timer);
return;
}
timer = setTimeout(function ()
{ func(); // calls the current function
++currentFunc; // sets the next function to be called
caller(args[currentFunc], timeout);
}, Math.floor(timeout));
}(args[currentFunc], timeout)); // pass in the timeout and the first function to run
}
函数inOrderTimeout(/*func1[,func2,func3,…funcN],超时*/)
{var timer;//用于稍后超时
var args=arguments;//允许嵌套函数访问父函数参数
var numToRun=args.length-1;//传递的函数数
如果(numToRun<1)返回;//damm,则不运行任何内容
var currentFunc=0;//索引计数器
var timeout=args[numToRun];//超时应该在最后一个函数参数之后
(函数调用方(func,timeout)//name以便可以递归
{if(currentFunc>numToRun-1)
{//最后一个,我们结束吧
清除超时(计时器);
返回;
}
定时器=设置超时(函数()
{func();//调用当前函数
++currentFunc;//设置要调用的下一个函数
调用者(args[currentFunc],超时);
},数学地板(超时);
}(args[currentFunc],timeout));//传入超时和要运行的第一个函数
}
< /代码> 您可以考虑使用jQuery DEFRIEDS(或者DEFERADS的其他实现),它可以非常优雅地处理这个模式。
需要注意的重要一点是,延迟完成的回调是按照添加它们的顺序执行的
var createCountFn = function(val){
return function(){
alert(val)
};
}
// tasks
var f1 = createCountFn(1),
f2 = createCountFn('2nd'),
f3 = createCountFn(3);
var dfd = $.Deferred();
dfd.done(f1).done(f2).done(f3);
dfd.resolve();
可以考虑使用jQuery DEFRIEDS(或者DEFELDE的其他实现),它可以非常优雅地处理这个模式。
需要注意的重要一点是,延迟完成c