【问题标题】:Understanding execution of WebAPIs with setTimeout & DOM Api使用 setTimeout 和 DOM Api 了解 WebAPI 的执行
【发布时间】:2022-01-08 19:22:20
【问题描述】:

我已经使用 JS 大约一年了,我还在学习它。我的问题在最后。

在第一个例子中:

console.log('Start');

setTimeout(()=> console.log('inside callback'), 0); 

console.log('End');

输出

Start
End
inside callback

我知道即使超时是0,它仍然必须转到浏览器WebApi(setTimeout api)并立即推入回调队列等待主线程空闲(当前正在执行console.log( '结尾'))。一旦线程空闲,就会执行回调并打印“内部回调”。

按照这种方法,我尝试用另一个 WebAPI 即 DOM API 来试验它。

这一次,我使用 document.querySelectorAll() 代替 setTimeout

console.log('Start');

console.log(document.querySelectorAll('img'))

console.log('End');

输出

Start 
NodeList(4) [img.bar-sm.-avatar.js-avatar-me, img.bar-sm.avatar.s-avatar--image, img, img]
End

这一次我们在 END 打印之前看到 DOM API 输出。

我知道输出,但我想了解其背后的流程。

为什么不遵循 setTimeout 之类的模式?

如果在单独的线程上处理,为什么 DOM 输出没有出现在“End”之后。

是否遵循以下流程:

document.querySelectorAll -> webAPI -> 回调队列 -> 主线程

DOM API 是否必须通过回调队列并等待主线程为空如果是这样?为什么我们这次的控制台顺序与 setTimeout 不同

我仍在学习,非常感谢您的解释。如果我误解了,请指出任何内容。谢谢。

【问题讨论】:

  • setTimeout()timeout ms 之后将回调推送到将被先进先出处理的queue.querySelectorAll() 立即执行。
  • 是的,我的最佳解释是因为 querySelectorAll 是同步的,而 setTimeout 是异步的。对吗?
  • setTimeout() 本身也是同步的。但它会触发一个异步操作,即将提供的回调添加到稍后处理的队列中。
  • “setTimeout() 本身也是同步的”我不确定你的意思。 developer.mozilla 提到“setTimeout() 是一个异步函数,这意味着计时器函数不会暂停函数堆栈中其他函数的执行。” developer.mozilla.org/en-US/docs/Web/API/setTimeout
  • 抱歉,我在这里可能有点挑剔.../* code/statement A */; setTimeout(); /* code/statement B */; 将始终以相同的顺序执行:A -> setTimeout() -> B,因为那部分是同步的。但是回调,setTimeout() 调用的预定部分,会在稍后时间执行 -> 异步。所以说setTimeout() 是异步的(几乎)是正确的,因为它的相关部分(回调)实际上是异步的。

标签: javascript dom settimeout event-loop


【解决方案1】:

原因是document.querySelectorAll 是同步方法,而setTimeout 是异步方法。

JS 脚本在 DOM 所在的同一环境中执行,因此它不是异步的。异步事件是通常被发送到另一个环境的事件(稍后由事件循环处理)

这是基于事件循环的并发模型的一部分,它实际上负责执行代码,收集和处理事件。 setTimeout 函数使用 2 个参数调用:要添加到回调队列的消息和时间值(可选;默认为 0)。时间值表示消息实际被推入队列的(最小)延迟。如果队列中没有其他消息,并且堆栈为空,则在延迟后立即处理该消息。但是,如果有消息,则 setTimeout 消息将不得不等待其他消息被处理,因此,第二个参数表示最短时间(不是保证时间)。因此,消息“结束”将在回调“内部回调”中的消息被处理之前写入控制台,因为延迟是运行时处理请求所需的最短时间(不是保证时间)。

document.querySelectorAll 是在 DOM 所在的同一环境中执行的脚本的一部分,因此它不是异步的,将立即执行。

DOM 操作是同步的。话虽如此,浏览器响应 DOM 更新而重新渲染页面的过程是异步的。这会给人一种异步 DOM 更新的错觉。

更多关于 JavaScript 事件循环 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

【讨论】:

  • 那么这是否意味着所有浏览器 DOM API 都是同步的?
  • 我会为你的问题添加答案,因为这是一个好问题
  • 现在请看@WaleedAhmad
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-13
  • 1970-01-01
  • 2020-07-31
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多