我最近看到一个presentation on the JS event loop,坦白地说,这很棒,但我现在对JS调用堆栈有一个挥之不去的问题。如果你考虑全局执行上下文,比如main(),main()从未解决过?我的理由是,如果是,那么JS程序就完整了,不会发生回调。
- 修改
我的主要兴趣是如何表示与回调队列相关的调用堆栈。如果在将新帧推入堆栈之前,事件循环被称为等待调用堆栈为空,那么循环将等待直到程序完成,并且回调不会产生任何影响。
我想这意味着事件循环等待只剩下一个帧(主执行上下文),而不是没有帧。
答案 0 :(得分:3)
如果您将全局执行上下文视为main()
没有。 main
不是global execution context,它是最初在该上下文中运行的代码。全局环境是 - 通过关闭 - 在全局代码运行后仍然保留用于未完成的回调,在程序完成之前它不会被垃圾收集。
是main()从未解决过吗?
当然是。 main()
是invocation of any global code - 基本上,当您在网页中加载脚本并执行时(是的,这可能会多次发生)。或者告诉节点执行的全局程序。一旦该代码完成运行,它确实会弹出堆栈,正如您在会谈动画中所看到的那样。它不会继续运行",因为这会阻止事件循环。
我的理由是,如果是,那么JS程序就完成了,不会发生回调。
没有。该脚本可能已经完成,是的,但您的程序(浏览器环境,节点等)尚未完成。事件循环仍在旋转(或者,确切地说:刚开始旋转)。
事件循环将查看正在进行的异步任务(XHR,超时,文件IO等),并注意到仍有一些工作正常。该程序不会退出。一旦这些任务中的一个(或多个)完成,他们就会将回调放在回调队列中,在那里它被事件循环拾取,并通过在全新的调用堆栈上执行它来处理。当该堆栈再次为空时,事件循环将重新处于控制状态,并从队列中获取回调,直到它为空。然后,它再次查看是否仍有正在进行的任务(其中一个回调可能产生了新的任务),并且只有当没有任务时,程序才会真正结束,并且全局环境可能会被破坏。
所以是的,确实有时候执行一个javascript程序,其中callstack是空的,只有事件循环快乐地旋转 - 实际上,大多数情况下都是这种情况。
答案 1 :(得分:2)
正如您所说,main()是全局执行上下文。它还活着,直到:
因此,除非上述用例之一发生,否则运行时仍处于活动状态,事件循环(将处理任务队列)也是如此。