总体目标
我想了解以下 JavaScript 环境的组件是如何作为一个系统相互连接的:
- JavaScript 引擎
- 事件循环(Event Loop)
- 事件队列(Event Queue)
我们可以将此限制在 浏览器环境 中,因为 Node 已经在另一篇文章中介绍过 (这里)。
我了解的事情:
JavaScript 是单线程的,因此只有一个调用栈。
JavaScript 环境仅提供少数几个真正异步的函数。这些函数可能包括 setTimeout()、setInterval() 和 I/O 函数。
开发人员不能创建自己的异步函数,而必须使用其中之一。
JavaScript 本身是同步运行的,但通过其异步函数可以在当前调用栈清空后回调原本会阻塞的函数。
示例:
console.log(‘Sync code started…’);
setTimeout(function asyncLog() {
console.log(‘Async function has completed’)
}, 2000);
console.log(‘Sync code finished…')
示例步骤:
(如果我有误,请纠正)
- 记录“同步代码已启动…”
- 将setTimeout添加到堆栈中,但立即返回控件
- 将setTimeout发送到不同的“线程”或“工作器”外部,超出JavaScript的单个线程以计算2000毫秒
- 记录“同步代码已完成…”
- 2000毫秒后,asyncLog()被推送到事件队列中
- 因为调用堆栈已清除,事件循环检查待处理回调的事件队列
- 事件循环从队列中删除asyncLog()并将其推送到堆栈中
- 记录“异步函数已完成”
- 现在调用堆栈已清除
问题
如果有人能够总览异步函数(例如setTimeout)从第一次命中调用堆栈到它们被回调到调用堆栈的过程,这些问题就不需要逐个回答。
- 第3步中,谁产生了这个新线程?是浏览器吗?
- 这个新线程被阻塞了对吗?
- 如果您有一个创建1000个setTimeout的循环,会创建1000个“线程”吗?
- 一次可以生成多少个线程的限制是什么?
- 新线程执行完毕后,它如何进入队列?
- 谁提供了事件队列?
- 谁提供了事件循环?
- 事件循环是否轮询事件队列?
- JavaScript的线程是否知道事件循环?还是事件循环只是将事物推到堆栈上?
- 事件循环如何知道堆栈已清除?