我正在查看TODO MVC Example with shadow DOM and customElements,在litRender.js中,invalidate()
函数中有一个奇怪的代码:'await 0'。我想知道这段代码的目的。
我在Google上做了一些搜索,但是找不到类似的情况。我对javascript和Webpack非常陌生,所以我不知道如何调试应用程序(我尝试使用--devtool选项将其重新捆绑,但出现错误)。
作者的解释是(抱歉翻译):
可以在litRender.js
下找到
src/libs
,它有助于呈现此应用程序的每个组件。每个组件使用litRender
形式的class SomeComponent extends LitRender (HTMLElement)
组合。如果内容被多次更新,那么时间代码旨在通过不每次渲染来帮助提高性能,则它收集了渲染时间。在扩展它的组件上调用this.invalidate将保留对组件中定义的render函数的调用。
如上所述,invalidate()
用于渲染阴影DOM。 Here's how the author uses it。
我想知道litRender.js
中的'await 0'实际上是什么。
答案 0 :(得分:1)
await
语句必须用在async
代码中,以便文档在说明部分说here,await
将用于暂停执行该功能直到承诺被解决或被拒绝为止,因此,如果await
旁边的语句不是承诺,那么JS将视为已解决的承诺。
希望它可以帮助您理解。
答案 1 :(得分:0)
一年后,我终于找到答案:await 0
是为了释放事件循环以便浏览器可以绘制框架。
注意:我的解释很冗长,语法用法也很差。最好阅读上面链接的MDN文档。
由于JS被设计为单线程(当有网络工作者时)语言,因此它具有一个称为 event loop 的并发模型。考虑以下情况:
console.log('before timeout')
setTimeout(() => console.log('inside timeout'), 0)
console.log('after timeout')
结果将是:
before timeout
after timeout
inside timeout
一开始可能会造成混乱。您可能会认为:超时设置为0,因此它将在执行下一行代码之前执行其回调!但这不是真的。
要理解上面的代码,首先让我们看看JS如何处理代码执行。它具有一个名为 stack 的存储,该存储可跟踪当前函数执行的来源。
function a() {
console.log('a()')
}
a()
console.log('end')
在上面的代码中,首先执行括号中的代码。然后,将执行功能a。此时,堆栈将如下所示:
a
(Main) -> code outside every brackets
如果某个函数调用了另一个函数,则被调用的函数会堆叠在前一个函数上。现在,函数end和JS从栈顶清除它,返回到先前位置,执行剩余的代码,直到到达末尾,依此类推。通过利用堆栈,JS可以找出当前函数结束之后的去向。
然后,当我们执行setTimeout时会发生什么?这里重要的是setTimeout不是语言功能,而是浏览器要处理的平台功能。浏览器等待给定时间,同时继续执行以下代码。然后超时结束,浏览器需要执行其回调,但是问题是另一段代码可能仍在执行。为了解决这个问题,浏览器将回调作为 task 并将其注册在 task queue 中。堆栈为空时,将按顺序执行其中的任务。
这说明了第一个代码段的奇怪行为:setTimeout的回调被注册为任务,并等待直到堆栈为空。记录第二条消息后,主代码执行结束,并且回调最终得到执行。
承诺的处理方式类似(但与microtask相同)。不管等待的右边是否是一个承诺,等待之后需要执行的每个代码都被注册为微任务。这样做的主要好处与以下事实有关:浏览器仅在堆栈为空时才绘制框架。通过在微任务执行之前将剩余的代码注册为微任务堆栈为空,因此浏览器可以在该时间绘制框架。