线程是进程中的最小单位。执行一段指令所需的时间。打开tab相当于创建一个进程,http请求则是一个线程。
js是单线程执行的。JS运行的时候会阻止dom解析渲染。如果js可能修改dom时页面还在解析,则会浪费。这就是单线程的好处。
HTML5允许多线程。开始执行js代码时,把任务分成同步和异步任务。同步任务放入执行栈。异步任务会进入异步进程处理,事件函数等待事件发生,定时函数等待延时时间到,然后进入任务队列中。
先执行执行栈中的同步任务。等执行栈空了,再按照次序读取任务队列(消息队列)中的异步任务到执行栈开始执行。
主线程不断重复获取任务、执行任务的这种机制就叫做事件循环。
不同的任务源会被分配到不同的 Task 队列中,任务源可以分为 微任务(microtask) 和 宏任务(macrotask)。在 ES6 规范中,microtask 称为 jobs,macrotask 称为 task
不同类型的任务会进入对应的Event Queue。
事件循环的顺序,决定js代码的执行顺序。进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。
- 执行同步代码,这属于宏任务
- 执行栈为空,查询是否有微任务需要执行
- 执行所有微任务
- 必要的话渲染 UI
- 然后开始下一轮 Event loop,执行宏任务中的异步代码
微任务
- process.nextTick
- promise
- Object.observe
- MutationObserver
宏任务
- script
- setTimeout
- setInterval
- setImmediate
- I/O
- UI rendering