为什么 setTimeout(fn, 0) 有时很有用?

2023-12-13

我最近遇到了一个相当讨厌的错误,其中代码正在加载一个<select>通过 JavaScript 动态地。这个动态加载的<select>有一个预先选定的值。在 IE6 中,我们已经有代码来修复所选的<option>,因为有时<select>'s selectedIndex值将与所选的不同步<option>'s index属性,如下:

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()?


问题中存在一个竞争条件之间:

  1. 浏览器尝试初始化下拉列表,准备更新其选定的索引,并且
  2. 用于设置所选索引的代码

您的代码始终赢得这场比赛,并尝试在浏览器准备就绪之前设置下拉选择,这意味着会出现错误。

这场竞赛的存在是因为 JavaScript 有一个单线程执行与页面渲染共享。实际上,运行 JavaScript 会阻止 DOM 的更新。

您的解决方法是:

setTimeout(callback, 0)

调用setTimeout带有回调,并且第二个参数为零将安排回调运行异步地,在尽可能短的延迟之后 - 当选项卡具有焦点并且 JavaScript 执行线程不忙时,延迟时间约为 10 毫秒。

因此,OP 的解决方案是将所选索引的设置延迟大约 10 毫秒。这给了浏览器一个初始化 DOM 的机会,修复了 bug。

每个版本的 Internet Explorer 都表现出奇怪的行为,有时这种解决方法是必要的。或者,它可能是 OP 代码库中的一个真正的错误。


参见菲利普·罗伯茨的演讲“事件循环到底是什么?”以获得更彻底的解释。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 setTimeout(fn, 0) 有时很有用? 的相关文章

随机推荐

  • 如何向 Firefox 插件添加循环计时器?

    我正在尝试使用新的插件构建器预览 https builder addons mozilla org 创建一个插件 并且我需要一个大约每 10 分钟运行一次的函数 我尝试了 setInterval 和 setTimeout 但它们都返回以下错
  • JavaScript 中的 getElementsByTagName [重复]

    这个问题在这里已经有答案了 我对纯 JavaScript 的语法很陌生 你知道为什么 getElementsByTagName 在我的简单测试中不起作用吗 var btn document getElementsByTagName butt
  • 将带有日期的 stderr 从 Cron 重定向到日志文件

    bash 脚本从 cron 运行 stderr 被重定向到日志文件 这一切都工作正常 代码是 10 5 22 opt scripts sql fetch 2 gt gt opt scripts logfile txt 我想将日期添加到日志文
  • Java:CompletableFuture.supplyAsync() 不调用异步方法[重复]

    这个问题在这里已经有答案了 让我们假设以下主要方法 public class Async public static void main String args throws Exception CompletableFuture supp
  • java 强制 JTextField 仅为大写

    有没有办法强制所有用户输入JTextFieldJava 中要大写吗 一个完整的工作示例可能会帮助你 import java awt Dimension import java awt FlowLayout import javax swin
  • 抓取动态数据硒 - 无法定位元素

    我对抓取非常陌生 有一个问题 我正在抓取世界计量仪的新冠数据 因为它是动态的 我用硒来做 代码如下 from selenium import webdriver import time URL https www worldometers
  • 正则表达式:匹配除一个单词之外的所有内容[重复]

    这个问题在这里已经有答案了 我正在寻找一种正则表达式模式 它可以匹配除一个单词之外的所有内容 例如 决议 monitors resolutions Should not match monitors 34 Should match moni
  • 从 C 代码设置 ALSA 主音量

    我一直在寻找一个简单的 C 代码示例来设置 ALSA 混音器的主音量 但找不到任何简单的内容来完成这个所谓的常见操作 我对 ALSA 完全不熟悉 所以制作我自己的最小示例需要时间 如果有人能提供一个 我会很高兴 以下内容对我有用 参数体积应
  • PHP SQL 更新数组

    我最初对以下内容感到满意 以便将第 1 行和第 2 行更新为相同的值 status 1 if POST sql UPDATE table SET status 1 WHERE id IN 1 2 db gt query sql if db
  • 正则表达式在匹配链接行为时删除 - Python

    我想删除整个链接 https www linkedin com in ACoAAAJv1l4BATlBOVqhEEaqrVNojJPWnID9Nk0 当链接包含ACo正则表达式应该从我的模式中删除整个链接 regex2 re compile
  • Asp.net 功能中是否存在带有验证器的电子邮件?

    我的要求是 如果用户在 asp net 文本框中输入电子邮件 它应该从数据库进行验证 该电子邮件是否存在 并且应该停止提交表单 是否有任何内置功能或者我必须自己制作 谢谢 阿提夫 你必须自己做 您可以按如下方式使用 AJAX
  • SQL Server:批量加载失败。数据文件中第 1 行第 1 列的列太长

    请有人在这里帮助我 已经看了几个小时了 但没有任何结果 我使用以下脚本在 SQL Express 2008 R2 中创建了一个表 CREATE TABLE Features ID int not null identity 1 1 Stop
  • 在 Delphi XE2 上使用运行时包进行构建

    我发现了类似的问题 但没有找到答案 问题是如何轻松地将所有已安装的运行时包添加到 Delphi XE2 项目中的 项目选项 包 运行时包 列表中 在 XE 和早期版本中 您可以通过简单地选中 取消选中 使用运行时包构建 来完成此操作 这些包
  • IntelliJ 在提交后显示 GIT 差异

    首先 我创建新分支 然后 我在类中添加一个新的代码行 Intellij 在左侧显示了我添加的新行的不同颜色 然后 我提交我的代码 此后 IntelliJ 不再显示我在左侧添加了新行 我不想要这样 我如何配置 IntelliJ 以便它显示与之
  • Doctrine 实体管理器导致页面中断

    我是 Symfony2 的新手 并尝试显示一个列出实体项目的页面 但是 一旦我使用下面的代码 分页符就会出现 未收到数据错误 或 ERR EMPTY RESPONSE 导致我认为我的路线不起作用并引发问题here但问题与教义有关 publi
  • Java 中希尔排序算法的变体

    有没有办法计算 for 循环的起点及其调整 原始循环有这些条件 for int gap a length 2 gap gt 0 gap 2 我调整它来设置希巴德希尔排序的条件并得到这个 for int gap int Math pow 2
  • 如何在 Rails 中渲染不同格式的一部分?

    我正在尝试生成包含一些 HTML 的 JSON 响应 因此 我有 app views foo bar json erb someKey some value someHTML 我想要它渲染 app views foo baz html er
  • 根据键值将数组拆分为更小的数组?

    我有在我的网站上执行关键字搜索的 mysql 搜索结果 它们按会员级别 0 3 排序 然而 我需要以不同的方式显示排名 比如排名 3 的格式比其他排名更突出 我正在考虑将行分成单独的数组 因此 像 array0 将包含排名为 0 的所有行等
  • 如何使用另一个字段登录 Django Allauth?

    我已经设置成功了django allauth以及自定义用户模型 让用户直接使用电子邮件和密码或通过 Facebook 登录 在这种情况下 电子邮件从 Facebook 获取并保存在自定义用户模型的电子邮件字段中 我还创建了一个移动字段 目前
  • 为什么 setTimeout(fn, 0) 有时很有用?

    我最近遇到了一个相当讨厌的错误 其中代码正在加载一个