js机制
单线程
一次只做一件事。
同步任务与异步任务
同步任务
在主线程上排队执行的任务,前一个任务执行完毕,才能执行后一个任务;
异步任务
不进入主线程,而是进入任务队列,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
总结
只要主线程空了,就会读取任务队列,这就是js的运行机制。
同步与异步的区别: 会不会阻塞代码的执行。
Microtasks Macrotasks
任务队列不止一个,还有 microtasks 和 macrotasks
microtasks:
process.nextTick
promise
Object.observe
MutationObserver
macrotasks:
setTimeout
setInterval
setImmediate
I/O
UI渲染
执行原理:
事件循环的顺序,决定了JavaScript代码的执行顺序。它从script(整体代码)开始第一次循环。之后全局上下文进入函数调用栈。直到调用栈清空(只剩全局),然后执行所有的micro-task。当所有可执行的micro-task执行完毕之后。循环再次从macro-task开始,找到其中一个任务队列执行完毕,然后再执行所有的micro-task,这样一直循环下去。
注意点
包裹在一个 script 标签中的js代码也是一个 task 确切说是 macrotask。
在每一次事件循环中,macrotask 只会提取一个执行,而 microtask 会一直提取,直到 microtasks 队列清空。
而事件循环每次只会入栈一个 macrotask ,主线程执行完该任务后又会先检查 microtasks 队列并完成里面的所有任务后再执行 macrotask。
一个事件循环(event loop)会有一个或多个任务队列(task queue)
task queue 就是 macrotask queue
每一个 event loop 都有一个 microtask queue
task queue == macrotask queue != microtask queue
一个任务 task 可以放入 macrotask queue 也可以放入 microtask queue 中
测试
|
|
答案为:
start
promise 1
promise 2
setInterval
setTimeout 1
promise 3
promise 4
setInterval
setTimeout 2
promise 5
promise 6
简单来讲,整体的js代码这个macrotask先执行,同步代码执行完后有microtask执行microtask,没有microtask执行下一个macrotask,如此往复循环至结束