Bar*_*dys 1 javascript v8 event-loop
我知道当调用堆栈为空时,消息从队列进入调用堆栈.如果事件循环可以将消息从队列直接推送到调用堆栈而不等待,那会不会更好?这种行为背后的原因是什么?如果事件循环会在确切的时间推送消息,我们总是可以依赖于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");Run Code Online (Sandbox Code Playgroud)
由于一致性原因,它可能永远不会改变,但我仍然很好奇.也许我没有看到任何东西,并且在等待空堆栈的概念背后存在严重的技术原因.您是否可以访问有关JS中的体系结构决策的文章,或者您可能知道在需要此行为时的基本示例?有很多关于JS如何工作的文章,但我找不到类似"为什么事件循环完全按照这种方式工作"的内容.任何帮助将不胜感激.
V8开发人员在这里.这个问题似乎是基于对"调用堆栈"的误解:它不是任何人都可以推送的数据结构.相反,当一堆函数相互调用时,它是当前状态的术语.将另一个函数"推"到调用堆栈的唯一方法是当前正在执行的函数调用它.如果事件系统在随机位置插入随机调用到您的函数中,那将导致一个非常奇怪的编程模型.
您可以设计一个概念上相似的编程环境,而不是将任何东西推送到调用堆栈,它会做什么是中断和挂起当前正在执行的任何操作,并执行setTimeout-scheduled函数(或事件处理程序等),然后恢复之前的执行.您必须解决的一个问题是:如果重复该怎么办,即如果调度的函数被另一个被另一个预定函数中断的预定函数中断,该怎么办?如果计划的函数需要永远完成,那么先前执行的代码何时才能再次进行呢?此外,虽然这可以在单线程世界中完成,但是获得随机中断是并发性的(从一致性的角度来看,它等同于并行/多线程),所以你需要像锁一样的同步原语(基本上,有函数说"不要打断这一部分"的方式 - 这反过来意味着你实际上无法保证调度请求的准确性).不要低估所有这会给程序员带来的复杂性成本:在编写代码时,他们必须记住任何时候都可能出现任何中断,而另一方面,任何一个函数可能想要处理的数据可能尚未准备好,因为生成它的另一个函数还没有完成运行.
简而言之,JavaScript的事件循环系统就是这样,因为语言避免了并发性,并且随机中断执行其他函数的函数就是并发性,即使在单线程系统上也是如此.