'await 0'的用法是什么?

时间:2018-12-22 13:37:23

标签: javascript lit-html

摘要

我正在查看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'实际上是什么。

2 个答案:

答案 0 :(得分:1)

await语句必须用在async代码中,以便文档在说明部分说hereawait将用于暂停执行该功能直到承诺被解决或被拒绝为止,因此,如果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相同)。不管等待的右边是否是一个承诺,等待之后需要执行的每个代码都被注册为微任务。这样做的主要好处与以下事实有关:浏览器仅在堆栈为空时才绘制框架。通过在微任务执行之前将剩余的代码注册为微任务堆栈为空,因此浏览器可以在该时间绘制框架。