javascript - 调用堆栈和事件循环 - 为什么要等待空堆栈?
问题描述
我知道当调用堆栈为空时,消息会从队列中进入调用堆栈。但是,如果事件循环可以将消息从队列直接推送到调用堆栈而不等待,那不是更好吗?这种行为背后的原因是什么?如果事件循环会在准确的时间推送消息,我们总是可以依赖 setTimeout 等函数。
setTimeout(() => console.log("I want to be logged for 10ms, but I will never be :("), 10);
// some blocking operations
for(let i = 0; i < 500000000; i++){
Math.random() * 2 + 2 - 3;
}
console.log("I'll be logged first lol");
由于一致性原因,它可能永远不会改变,但我仍然很好奇。也许我什么都没看到,等待空堆栈的概念背后有严重的技术原因。您是否可以访问一些有关 JS 中的架构决策的文章,或者您是否知道需要这种行为的基本示例?有很多关于 JS 如何工作的文章,但我找不到像“为什么事件循环完全那样工作”这样的文章。任何帮助将不胜感激。
解决方案
V8 开发人员在这里。这个问题似乎是基于对“调用堆栈”是什么的误解:它不是任何人都可以将东西推送到上面的数据结构。相反,它是一组函数相互调用时事物的当前状态的术语。将另一个函数“推入”调用堆栈的唯一方法是在当前执行的函数调用它时。如果事件系统在你的函数中随机插入随机调用,那将导致一个非常奇怪的编程模型。
您可以设计一个概念上相似的编程环境,但不是将任何内容推送到调用堆栈上,而是中断和暂停当前正在执行的任何内容,然后执行setTimeout
-scheduled 函数(或事件处理程序等),然后恢复之前的执行。您必须解决的一个问题是:如果这种情况重复发生,即,如果预定功能被另一个预定功能中断,而另一个预定功能又被另一个预定功能打断怎么办,等等?如果一个计划函数需要永远完成怎么办:之前执行的代码什么时候才能再次取得进展?此外,虽然这可以在单线程世界中完成,但获得随机中断是并发(从一致性的角度来看相当于并行/多线程),所以你需要像锁这样的同步原语(基本上,有一种让函数说“不要打断这一部分”的方式——这反过来意味着你实际上不能保证调度请求的准确性)。大学教师'
所以简而言之,JavaScript 的事件循环系统之所以如此,是因为该语言避免并发,随机中断函数执行其他函数是并发的,即使在单线程系统上也是如此。
推荐阅读
- c++ - Add a set of numbers in C++
- c# - 如何将蒙特卡罗模拟拟合到二维矩形阵列中
- python - 使用 Python 3 在 Windows 中查找插入符号位置
- java - Java 格式化一整行
- sql - 重组表并检查值
- bash - 即使只有一个短语要替换,我如何使用 sed 替换整行?
- swift - Swift:动画 NSLayoutConstraint 不起作用
- javascript - 异步函数调用上的同步函数调用与“等待”的行为
- dafny - 断言、forall 和映射:通用量词不适用于映射
- c - 在某些情况下,链接器允许多个模块定义具有相同名称的全局符号?