dit*_*tto 6 javascript lit-html
我正在查看带有 Shadow DOM 和 customElements 的 TODO MVC 示例,在litRender.js中,函数中有一个奇怪的代码invalidate()
:'await 0'。我想知道这段代码的目的是什么。
我在谷歌上进行了一些搜索,但找不到类似的案例。我对 javascript 和 Webpack 非常陌生,所以我不知道如何调试应用程序(我尝试使用 --devtool 选项重新捆绑它,但出现错误)。
作者的解释是(抱歉翻译):
litRender.js
可以在下面找到src/libs
并帮助渲染此应用程序的每个组件。每个组件都litRender
使用class SomeComponent extends LitRender (HTMLElement)
. 如果内容更新了多次,则时间代码旨在通过不每次渲染来帮助提高性能,它会收集渲染时间。在扩展它的组件上调用 this.invalidate 将保留对组件中定义的渲染函数的调用。
正如上面作者提到的,invalidate()
shadow DOM是用来渲染的。下面是作者的使用方法。
我想知道 'await 0' 的litRender.js
真正作用是什么。
一年后我终于找到了答案:await 0
用于释放事件循环,以便浏览器可以绘制框架。
注意:我的解释很冗长,并且有一些糟糕的语法用法。阅读上面链接的 MDN 文档可能会更好。
由于 JS 被设计为单线程(虽然存在 Web Worker)语言,因此它有一个称为事件循环的并发模型。考虑以下情况:
console.log('before timeout')
setTimeout(() => console.log('inside timeout'), 0)
console.log('after timeout')
Run Code Online (Sandbox Code Playgroud)
结果将是:
before timeout
after timeout
inside timeout
Run Code Online (Sandbox Code Playgroud)
一开始可能会令人困惑。你可能会想:超时时间设置为0,这样它就会在执行下一行代码之前执行回调!但事实并非如此。
为了理解上面的代码,我们首先看看JS是如何处理代码执行的。它有一个称为堆栈的存储,用于跟踪当前函数执行的来源。
before timeout
after timeout
inside timeout
Run Code Online (Sandbox Code Playgroud)
上面的代码中,首先执行括号外的代码。然后,函数a将被执行。此时,堆栈将如下所示:
a
(Main) -> code outside every brackets
Run Code Online (Sandbox Code Playgroud)
如果某个函数调用另一个函数,则被调用的函数将堆叠在前一个函数上。现在函数end和JS将其从栈顶清除,返回到之前的位置,执行剩余的代码直到到达末尾,依此类推。通过利用栈,JS 可以知道当前函数结束后该去哪里。
那么当我们执行setTimeout时会发生什么呢?这里重要的是 setTimeout 不是语言功能,而是浏览器处理的平台功能。浏览器等待给定时间,同时继续执行以下代码。然后超时结束,浏览器需要执行其回调,但问题是另一段代码可能仍在执行。为了解决这个问题,浏览器将回调作为一个任务并将其注册到任务队列中。当堆栈为空时,其中的任务将按顺序执行。
这解释了第一个代码片段的奇怪行为:setTimeout 的回调被注册为任务,并等待堆栈为空。记录第二条消息后,主代码执行结束,回调最终执行。
Promise 的处理方式类似(但是作为microtask)。不管await的右边是否是一个promise,await之后需要执行的每一个代码都会被注册为微任务。这样做的主要好处与浏览器仅在堆栈为空时才绘制帧这一事实有关。通过在微任务执行之前注册剩余的代码,因为微任务堆栈变空,因此浏览器可以在该时间绘制帧。
归档时间: |
|
查看次数: |
1612 次 |
最近记录: |