【问题标题】:Is $(document).ready() executing in the main thread, or is it asynchronous?$(document).ready() 是在主线程中执行,还是异步的?
【发布时间】:2016-01-06 20:10:48
【问题描述】:

我在$(document).ready() 中使用图形可视化库,它似乎会阻止 UI。我期待$(document).ready() 在单独的线程中执行。

有人知道详情吗?也许我应该使用setTimeout 来异步运行代码?

编辑:

术语“异步”和“分离线程”在 JavaScript 中具有误导性。我不是 JavaScript 专家,我找不到更准确的术语。请参阅答案以进行澄清。

【问题讨论】:

  • $(document).ready()DOMcontentLoaded 相同!
  • @RayonDabre 不,存在差异。 onload 将等待所有可见的外部资源(例如内联图像)加载,而当它自己的 DOM 完全加载时准备执行,其行为类似于在 结束之前加载脚本。
  • @RayonDabre,DOMcontentLoaded 是否在主线程中执行?
  • @Amadan 那么好吧,我看到他刚刚进行了编辑。
  • @Jay,JavaScript 通常被认为具有单线程执行 我无法理解您使用的术语separate thread

标签: javascript jquery multithreading events asynchronous


【解决方案1】:

除了 Web Workers(不能直接访问 DOM)之外,JavaScript 在单线程中运行。 $(document).ready() 是异步的,因为您传递给它的回调可能会在加载 DOM 时立即或稍后触发,但是当它的回调实际运行时,它是 JS 运行时正在处理的唯一事情。

例如,长时间运行的for 循环将阻塞 UI 线程,无论它是否处于就绪回调、事件处理程序、异步 XHR 的成功回调等。防止它阻塞的唯一方法线程将通过使用setTimeout 调度以后的块将其分成几个循环。

【讨论】:

  • 这样使用setTimeout听起来很神奇,有什么例子吗?
【解决方案2】:

在 JavaScript 中没有单独的线程。所有 JavaScript 都在单个线程中执行; UI 更新在同一个线程中执行。如果您的 JavaScript 很忙,则不会发生 UI 更新。 “异步”在这里有点误导性的术语;这意味着函数的执行将被推迟(但仍然在单个线程中)。

基本上,浏览器有一个执行队列。所有事件处理程序在被触发时都被放入执行队列;和超时功能一样。当任何没有调用者的函数退出时,队列中的下一个函数将被执行。 UI 更新也在同一个队列中。

所以当您执行$(document).ready(fn) 时,它(简单来说;jQuery 使它有点复杂,尤其是对于旧浏览器)将附加一个处理程序。当所有内容加载完毕后,浏览器会触发该处理程序,并将其放入执行队列。轮到它的时候,它会执行;它执行的任何 UI 更新都将在处理程序退出时绘制。

--

*) 单线程规则有一个例外:网络工作者。每个网络工作者都在自己的线程中运行,但他们能做的事情非常有限;基本上,只有计算(他们根本无法访问 UI)。

【讨论】:

    【解决方案3】:

    异步并不意味着多线程。 Javascript是基于事件的,当事情发生(事件发生)时会调用函数。事件监听函数不在单独的线程上执行,只是计划稍后执行。

    但是有一种旧技术可以在没有浏览器对 Web Workers 的支持的情况下模拟多线程。它将整个任务拆分为推迟小任务。

    比如你写这个会导致阻塞:

    for (var i = 0; i < 10000000; i++) {
        // do something very slow
    }
    

    把它转成这个,它会并行执行,几乎就像多线程一样。

    (function step(i) {
        if (i < 10000000) {
            // do something very slow
            setTimeout(function() {step(i + 1)}, 1);
        }
    })(0);
    

    编辑:我刚刚意识到这会导致内存问题,因为在每一步关闭中我们都引用了上一步,使得 GC 无法清理内存。为了克服这个问题,把i从参数中去掉,然后像这样改变它(我用一个函数包装了整个东西,这样i就不会在外面被错误地改变了):

    (function() {
        var i = 0;
        (function step() {
            if (i < 10000000) {
                // do something very slow
                i++;
                setTimeout(step, 1);
            }
        })();
    })();
    

    【讨论】:

      猜你喜欢
      • 2010-09-08
      • 2021-12-07
      • 2020-04-14
      • 2017-09-14
      • 1970-01-01
      • 1970-01-01
      • 2014-11-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多