- Objective:
- Breadcrumb:
# 概念阐释
事件循环可以在JavaScript中运行非代码阻塞,模拟并发性。当运行[[JavaScript 异步编程]]函数时,事件循环管理了代码执行的顺序。
*非代码阻塞、并发、异步编程其实都是一回事,2个以上的线程同时执行。*

2种[[数据结构]]堆和调用栈与节点和[[Web API]]交互,Web API通过事件队列将消息传回堆栈,事件队列与调用堆栈的交互由事件循环管理。
### [[堆栈#^304f7d|堆]]
无序存储对象的内存块。当前使用的 JavaScript 变量和对象存储在堆中。
### 调用[[堆栈]]
当[[调用函数]]时,就会像堆栈中添加一个帧,一个帧代表一个要执行的代码,按照LIFO先进后出的顺序进入堆栈,当函数完成时,帧将从堆栈中删除。
```js
function foo() {
return function bar() {
return function baz() {
return 'I love CodeCademy'
}
}
}
console.log(foo()()());
```
#### 添加堆栈

#### 删除堆栈

### 事件队列
等待处理的函数的列表,从各种WebAPI或被调用的异步函数,按照**FIFO先进先出**的顺序等待进入队列。
### 事件循环
当堆栈为空时,事件队列中的事件将被添加到堆栈,循环这一过程。
### 节点和WebAPI
# 实例
```js
console.log("This is the first line of code in app.js.");
function usingsetTimeout() {
console.log("I'm going to be queued in the Event Loop.");
}
setTimeout(usingsetTimeout, 3000);
console.log("This is the last line of code in app.js.");
```
- `console.log("This is the first line of code in app.js."); `添加到堆栈中,执行,弹出;
- `setTimeout();`添加到堆栈中;
- 执行WebAPI,`setTimeout(usingsetTimeout, 3000); `在3秒钟后被推送到事件队列;
- 事件循环定期查询堆栈,为空时加入事件队列消息;
- `console.log("This is the last line of code in app.js.");`添加到堆栈中,执行,弹出。
- 最后一行执行完了,`usingsetTimeout()`被压入堆栈
- `console.log("I'm going to be queued in the Event Loop.");`添加到堆栈、执行、弹出
2. `usingsetTimeout`从堆栈中弹出。
# 相关内容
## 阻塞与非阻塞的区别
```js
//阻塞实例
console.log("I'm learning about");
for (let idx=0; idx < 999999999; idx++) {}
// The second console.log() statement is
// delayed by the for loop's execution
console.log("the Event Loop");
//非阻塞实例,用setTimeout(),会先执行2个console,再执行setTimeout;使用事件循环,不用在等待时停止代码执行
console.log("I’m learning about");
setTimeout(() => { console.log("Event Loop");}, 2000);
console.log("the");
```
- 这个例子中,JavaScript仍然是单线程,但事件循环启用了并发性
# 参考资料
- [Concurrency Model and Event Loop in JavaScript并发模型和事件循环](https://www.codecademy.com/courses/learn-intermediate-javascript/articles/javascript-concurrency-model-and-event-loop)
- [并发事件与事件循环](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Event_loop)