1. event loop 的描述
JavaScript 是单线程的,简单点说就是同一时间只能做一件事情,这样会导致一些问题,有些任务耗时较长,当然是不能停留在这里的,比如说网络请求需要三秒钟,肯定不能等着,要先去执行别的代码,回头去执行回调函数,这就是简单的事件循环机制的描述。异步的实现要基于回调来实现,event loop 就是异步回调的实现原理
Event Loop
即事件循环,是指浏览器或Node
的一种解决javaScript
单线程运行时不会阻塞的一种机制,也就是我们经常使用异步的原理。
2. JS 执行过程
Javascript
有一个 main thread
主线程和 call-stack
调用栈(执行栈),所有的任务都会被放到调用栈等待主线程执行。
原理图
JS调用栈 (图中的stack) 采用的是后进先出的规则,当函数执行的时候,会被添加到栈的顶部,当执行栈执行完成后,就会从栈顶移出,直到栈内被清空。
同步与异步任务
Javascript
单线程任务被分为同步任务和异步任务,同步任务会在调用栈中按照顺序等待主线程依次执行,异步任务会在异步任务有了结果后,将注册的回调函数放入任务队列中等待主线程空闲的时候(调用栈被清空),被读取到栈内等待主线程的执行。
宏任务与微任务的区分
在JavaScript
中,任务被分为两种,一种宏任务(MacroTask
)也叫Task
,一种叫微任务(MicroTask
)。
宏任务: 多是 webAPI
- setTimeout
- setInterval
- requestAnimationFrame
- script(整体代码)
- setImmediate (node)
- I/O
- UI rendering
微任务: ES5,6语法
- Promise.then
- queueMicroTask
- MutationObserver
- async/await (promise语法糖)
4. event loop 充当角色
- 如Call Stack为空(即同步代码执行完) Event Loop 开始工作
- 轮询查找Callback Queue,如有则移动到Call Stack 执行
- 然后继续轮询查找(永动机一样)
- DOM渲染会在call stack为空的时候尝试渲染
总结:说白了就是先做宏任务,有遇到微任务就追加在当前的宏任务后面,等宏任务做完了再做好这些微任务。倘若在执行宏任务时遇到了又一个宏任务时,则要等当前的宏任务和其所跟着的微任务全做完了,才能开始这个第二个宏任务,依次不断循环直到宏任务队(包括其所追加的微任务队列)全部做完了为止。
本文描述的是JS结合浏览器的event loop过程,与node中的event loop有些不同,感兴趣的小伙伴可以参考node官方文档