【问题标题】:Why can't WebWorkers have access to the DOM? [duplicate]为什么 WebWorkers 不能访问 DOM? [复制]
【发布时间】:2016-01-19 18:30:59
【问题描述】:

我们都知道我们可以启动一些网络工作者,给他们一些平凡的任务去做并在某个时候得到响应,在这个阶段我们通常会解析数据并以某种方式将其呈现给用户。

嗯...谁能提供一个相对深入的解释,为什么 Web Workers 不能访问 DOM?鉴于经过深思熟虑的 OO 设计方法,我只是不明白为什么他们不应该这样做?

已编辑:

我知道这是不可能的,也没有实际的答案,但我觉得我需要更深入的解释。如果您认为该问题与社区无关,请随时关闭该问题。

【问题讨论】:

  • 大多数汽车都有一个方向盘是有原因的,想想看……如果很多事情都在发生变化,那么将所有这些级联的变化整理出来需要大量的工作,这将做一个缓慢的布局。查看背景信息的一般并发问题。
  • 这是一种设计选择。 “并发性是hard”,不得不担心处理锁和信号量而困扰 DOM 只是 JavaScript 不希望你必须处理的事情。 @dave 引用的问题详细说明了所有考虑的原因和足够的深度。
  • 我认为这种选择只会有助于正确设计 MVC 应用程序。

标签: javascript jquery dom browser web-worker


【解决方案1】:

其他答案都是正确的; JS 最初是为了简化而设计为单线程的,此时添加多线程必须非常小心。我想详细说明一下 Web Workers 中的线程安全。

当您使用 postMessage 向工作人员发送消息时,会发生以下三种情况之一,

  1. 浏览器将消息序列化为 JSON 字符串,并在另一端(在工作线程中)反序列化。这会创建对象的副本。
  2. 浏览器构造消息的结构化克隆,并将其传递给工作线程。这允许使用比 1. 更复杂的数据类型进行消息传递,但本质上是相同的。
  3. 浏览器转让所有权消息(或部分消息)。这仅适用于某些数据类型。它是零拷贝,但是一旦主上下文将消息传输到工作上下文,它在主上下文中变得不可用。这也是为了避免共享内存。

说到 DOM 节点,

  1. 显然不是一个选项,因为 DOM 节点包含循环引用,
  2. 可以工作,但在只读模式下,因为工作人员对节点克隆所做的任何更改都不会反映在 UI 中,并且
  3. 不幸的是不是一个选项,因为 DOM 是一棵树,转移节点的所有权将意味着转移整个树的所有权。如果 UI 线程需要咨询 DOM 来绘制屏幕并且它没有所有权,这会带来问题。

【讨论】:

    【解决方案2】:

    浏览器中的整个 Javascript 世界最初设计时都进行了极大的简化 - 单线程(在 webWorkers 出现之前)。这个单一的假设使编写浏览器的代码变得更加简单,因为永远不会发生线程争用,也永远不会有两个活动线程试图同时修改相同的对象或属性。这使得在浏览器中编写 Javascript 和在浏览器中实现 Javascript 变得更加简单。

    然后,需要能够执行一些不会阻塞主线程的更长时间运行的“后台”类型的事情。好吧,将它放入现有浏览器中的唯一实用方法是确保这个“新”的 Javascript 线程永远不会弄乱现有的主线程。

    因此,它的实现方式是,它可以与主线程或主线程可以修改的任何对象(例如整个 DOM 和几乎所有主机对象)通信的唯一方式是通过消息传递,它的实现自然是同步的,并且不会出现线程争用。

    这是一个相关的答案:Why doesn't JavaScript get its own thread in common browsers?

    【讨论】:

      【解决方案3】:

      Web Workers 没有 DOM 访问权限,因为 DOM 代码不是线程安全的。 DOM 代码是指浏览器中处理 DOM 调用的代码。

      使线程不安全的代码安全是一个巨大的工程,主流浏览器都没有这样做。

      Servo 项目正在从头开始编写新的浏览器,我认为他们在编写 DOM 代码时考虑了线程安全。

      【讨论】:

      • 这不仅仅是“使 DOM 线程安全”的问题。所有访问 DOM 的 Javascript 程序都必须更改其行为以以线程安全的方式使用 DOM,否则您将到处都有竞争条件。如果多个线程可以修改该对象,即使像 if (domObj.prop === "foo") {domObj.prop = "fee";} 这样简单的事情也是竞争条件。
      • 这是不正确的。 WebWorkers 是一个全新的功能,不使用 WebWorkers 的旧代码不必更改。无法在 WebWorkers 中进行 DOM 调用的原因是浏览器的 DOM 实现无法处理多线程。
      猜你喜欢
      • 2017-09-10
      • 2017-02-28
      • 2016-11-25
      • 2019-05-04
      • 2014-12-15
      • 2019-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多