单线程
js是单线程的,意味着他同一时间只能做一件事,也就是说所有的任务代码需要排队来执行,一个任务完成之后才能开始下一个任务。
任务的排队被称作消息队列。
重复执行消息队列中的任务的这一操作被称作事件循环。
我们的js代码从上往下执行,但是难免会有一些异步操作,例如发起ajax请求,使用定时器操作。那么遇到异步操作时js是怎么处理的呢?
来看下以下代码:
console.log("a")
let r = new Promise(function (resolve, reject) {
console.log("b");
resolve()
});
r.then(() => console.log("c"));
setTimeout(() => { console.log("d") }, 0)
setTimeout(() => { console.log("e") }, 1000)
console.log("f")
如果不能在短时间得出准确的结论,那么就需要深入了解js中的事件执行机制了。
宏任务和微任务
对于消息队列中的任务,分为两类:
- 宏任务(macrotask ):setTimeout、setInterval
- 微任务(microtask):promise
宏任务中包含了微任务,一个宏任务执行完成,开始下一个宏任务。
就拿上面代码来说:
- 开始执行,发现了一些代码,放进一个宏任务中
- 先执行a
- 执行b
- 发现异步操作then,属于微任务,把他添加进当前宏任务中的微任务的队列
- 发现定时器d,setTimeout属于宏任务,添加到宏任务的队列
- 发现定时器e,setTimeout属于宏任务,添加到宏任务的队列
- 执行f
- 代码都已经执行完成,开始执行微任务队列,打印出c
- 微任务队列执行完成,开始执行下一个宏任务队列
- 直接打印出d,没有其他微任务,开始执行下一个宏任务队列
- 打印出e,所有宏任务执行完成