为什么setTimeout(fn,0)有时有用? [英] Why is setTimeout(fn, 0) sometimes useful?

查看:134
本文介绍了为什么setTimeout(fn,0)有时有用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我遇到一个相当讨厌的bug,其中代码是通过JavaScript动态加载一个< select> 。这个动态加载的< select> 具有预先选择的值。在IE6中,我们已经有代码来修复所选的< option> ,因为有时候< select> s selectedIndex 值将与所选的< option> 索引不同步属性,如下所示:

  field.selectedIndex = element.index; 

但是,此代码不起作用。即使字段的 selectedIndex 设置正确,错误的索引最终将被选中。但是,如果我在正确的时间卡住了一个 alert()语句,则会选择正确的选项。认为这可能是某种时间问题,我尝试了一些我以前在代码中看到的随机数:

  var wrapFn = (function(){
var myField = field;
var myElement = element;

return function(){
myField.selectedIndex = myElement.index;
}
})();
setTimeout(wrapFn,0);

这样工作!



我有一个解决我的问题的解决方案,但我很不安,我不知道为什么这会解决我的问题。有人有官方的解释吗?使用 setTimeout()?调用我的函数稍后可以避免什么浏览器问题?

解决方案

这是因为你正在做合作的多任务。



浏览器必须同时执行大量的事情,其中​​只有一个是执行JavaScript。但JavaScript中常常使用的其中之一就是要求浏览器构建一个显示元素。这通常被认为是同步完成的(特别是因为JavaScript不是并行执行),但不能保证是这种情况,JavaScript没有明确的等待机制。



解决方案是暂停JavaScript执行,让渲染线程赶上。而这是 setTimeout(),超时时间为 0 的效果。它就像C中的线程/进程输出。尽管它似乎说立即运行它实际上使浏览器有机会完成一些非JavaScript的事情,等待完成,然后再参与这一新的JavaScript



(实际上, setTimeout()重新排队执行队列末尾的新JavaScript。查看评论链接到更长的解释。)



IE6恰好更容易出现此错误,但我已经看到它发生在旧版本的Mozilla和Firefox。


I've recently run into a rather nasty bug, wherein the code was loading a <select> dynamically via JavaScript. This dynamically loaded <select> had a pre-selected value. In IE6, we already had code to fix the selected <option>, because sometimes the <select>'s selectedIndex value would be out of sync with the selected <option>'s index attribute, as below:

field.selectedIndex = element.index;

However, this code wasn't working. Even though the field's selectedIndex was being set correctly, the wrong index would end up being selected. However, if I stuck an alert() statement in at the right time, the correct option would be selected. Thinking this might be some sort of timing issue, I tried something random that I'd seen in code before:

var wrapFn = (function() {
    var myField = field;
    var myElement = element;

    return function() {
        myField.selectedIndex = myElement.index;
    }
})();
setTimeout(wrapFn, 0);

And this worked!

I've got a solution for my problem, but I'm uneasy that I don't know exactly why this fixes my problem. Does anyone have an official explanation? What browser issue am I avoiding by calling my function "later" using setTimeout()?

解决方案

This works because you're doing co-operative multi-tasking.

A browser has to do a number of things pretty much all at once, and just one of those is execute JavaScript. But one of the things JavaScript is very often used for is to ask the browser to build a display element. This is often assumed to be done synchronously (particularly as JavaScript is not executed in parallel) but there is no guarantee this is the case and JavaScript does not have a well-defined mechanism for waiting.

The solution is to "pause" the JavaScript execution to let the rendering threads catch up. And this is the effect that setTimeout() with a timeout of 0 does. It is like a thread/process yield in C. Although it seems to say "run this immediately" it actually gives the browser a chance to finish doing some non-JavaScript things that have been waiting to finish before attending to this new piece of JavaScript.

(In actuality, setTimeout() re-queues the new JavaScript at the end of the execution queue. See the comments for links to a longer explanation.)

IE6 just happens to be more prone to this error, but I have seen it occur on older versions of Mozilla and in Firefox.

这篇关于为什么setTimeout(fn,0)有时有用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆