一:js的两个特点
- 单线程异步无阻塞
- 基于事件驱动
二:主线程执行中遇到异步任务,会放到宏任务或微任务队列,继续执行主线程
1,宏任务
- script整体代码、
- setTimeout、
- setInterval、
- setImmediate、
- [Ajax]、DOM事件
2,微任务
- process.nextTick、
- MutationObserver、
- Promise.then
- catch finally
3,微任务先执行,而且是一次性要把微任务队列里的任务都执行完再去执行宏任务
setTimeout(()=>{
console.log('s1')
Promise.resolve().then(()=>{
console.log('p1')
})
Promise.resolve().then(()=>{
console.log('p2')
})
})
setTimeout(()=>{
console.log('s2')
Promise.resolve().then(()=>{
console.log('p3')
})
Promise.resolve().then(()=>{
console.log('p4')
})
})
s1
p1
p2
s2
p3
p4
代码执行顺序
- 此时宏任务队列和微任务队列都为空,开始执行代码
- 遇到定时器,是宏任务,放到宏任务队列,继续往下执行
- 又遇到一个定时器,是宏任务,放到宏任务队列,继续往下执行
- 主线程同步代码执行完毕,接着来看任务队列,先看微任务队列,为空,再看宏任务队列,有两个任务
- 先执行第一个宏任务
- 1)打印 s1
- 2)遇到一个Promise微任务,添加到微任务队列
- 3)又遇到一个Promise微任务,添加到微任务队列
- 每执行完一个宏任务,都会去看微任务队列有没有,有就全部执行完,此时有两个微任务,所以打印出 p1 p2
- 微任务执行完毕,再去执行下一个宏任务
- 1)打印 s2
- 2)遇到一个Promise微任务,添加到微任务队列
- 3)又遇到一个Promise微任务,添加到微任务队列
- 这个宏任务执行完,再去执行微任务 打印出 p3 p4
三:现在在微任务里再加入宏任务
setTimeout(()=>{
console.log('s1')
Promise.resolve().then(()=>{
console.log('p1')
setTimeout(() => {
console.log('h1')
});
})
Promise.resolve().then(()=>{
console.log('p2')
setTimeout(() => {
console.log('h2')
});
})
})
setTimeout(()=>{
console.log('s2')
Promise.resolve().then(()=>{
console.log('p3')
setTimeout(() => {
console.log('h3')
});
})
Promise.resolve().then(()=>{
console.log('p4')
setTimeout(() => {
console.log('h4')
});
})
})
按照上面的逻辑顺序结果应该是
s1
p1
p2
s2
p3
p4
h1
h2
h3
h4