JavaScript:彻底理解同步、异步和事件循环(Event Loop)https://segmentfault.com/a/1190000004322358
这一次,彻底弄懂 JavaScript 执行机制https://juejin.im/post/59e85eebf265da430d571f89
一、单线程
JS是单线程的,用于处理js代码的只有一个线程,可以理解为主线程。浏览器是多线程的,还有处理网络请求的、定时器的线程、事件线程等等。
二、同步和异步
同步:function(args...),执行某个函数能立即得到返回结果的。
异步:function(args...,callback),执行某个函数需要过一段时间才能得到结果的。
同步易导致阻塞,异步会使顺序混乱。
三、消息队列和事件循环
消息队列:异步函数的回调函数都放在消息队列
时间循环:主线程重复从消息队列中取消息、执行的过程。

console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
作者:ssssyoki
链接:https://juejin.im/post/59e85eebf265da430d571f89
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
第一轮事件循环流程分析如下:
- 整体script作为第一个宏任务进入主线程,遇到
console.log,输出1。 - 遇到
setTimeout,其回调函数被分发到宏任务Event Queue中。我们暂且记为setTimeout1。 - 遇到
process.nextTick(),其回调函数被分发到微任务Event Queue中。我们记为process1。 - 遇到
Promise,new Promise直接执行,输出7。then被分发到微任务Event Queue中。我们记为then1。 - 又遇到了
setTimeout,其回调函数被分发到宏任务Event Queue中,我们记为setTimeout2。
| 宏任务Event Queue | 微任务Event Queue |
|---|---|
| setTimeout1 | process1 |
| setTimeout2 | then1 |
-
上表是第一轮事件循环宏任务结束时各Event Queue的情况,此时已经输出了1和7。
-
我们发现了
process1和then1两个微任务。 - 执行
process1,输出6。 - 执行
then1,输出8。
好了,第一轮事件循环正式结束,这一轮的结果是输出1,7,6,8。那么第二轮时间循环从setTimeout1宏任务开始:
- 首先输出2。接下来遇到了
process.nextTick(),同样将其分发到微任务Event Queue中,记为process2。new Promise立即执行输出4,then也分发到微任务Event Queue中,记为then2。
| 宏任务Event Queue | 微任务Event Queue |
|---|---|
| setTimeout2 | process2 |
| then2 |
- 第二轮事件循环宏任务结束,我们发现有
process2和then2两个微任务可以执行。 - 输出3。
- 输出5。
- 第二轮事件循环结束,第二轮输出2,4,3,5。
- 第三轮事件循环开始,此时只剩setTimeout2了,执行。
- 直接输出9。
- 将
process.nextTick()分发到微任务Event Queue中。记为process3。 - 直接执行
new Promise,输出11。 - 将
then分发到微任务Event Queue中,记为then3。
| 宏任务Event Queue | 微任务Event Queue |
|---|---|
| process3 | |
| then3 |
- 第三轮事件循环宏任务执行结束,执行两个微任务
process3和then3。 - 输出10。
- 输出12。
- 第三轮事件循环结束,第三轮输出9,11,10,12。
整段代码,共进行了三次事件循环,完整的输出为1,7,6,8,2,4,3,5,9,11,10,12。
(请注意,node环境下的事件监听依赖libuv与前端环境不完全相同,输出顺序可能会有误差)
作者:ssssyoki
链接:https://juejin.im/post/59e85eebf265da430d571f89
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
本文深入解析JavaScript的单线程特性、同步与异步执行原理,以及事件循环机制。通过实例详细阐述消息队列和时间循环如何影响代码执行顺序。
3616

被折叠的 条评论
为什么被折叠?



