loop循环
js代码执行过程中,除了依靠函数调用栈决定函数的执行顺序之外,还依靠任务队列搞定另外一些代码的执行,这整个过程我们称为事件循环过程
一个线程中,事件循环是唯一的,但是任务循环可以有多个,任务可以分为宏任务和微任务
宏任务
setTimeout
setImmediate
setInterval
I/O
ui render
微任务
promise.then
nextick
async await
MutationObserver
V8的垃圾回收过程
规则
1.在每一个宏任务中定义一个微任务队列,当一个宏任务执行完成之后就去查看其微任务队列是否为空,如果不为空则执行微任务队列,如果为空则执行下一个宏任务
2.promise里的直接执行,.then算下一大队列微任务;如果遇到return promise.resolve,则将后面的放到第三大队微任务
3.async 本行的内容立刻执行,后面的内容按顺序添加到微任务队列.
node中的事件循环
nodejs三个非常重要的阶段
1.timmer阶段 定时器时间到了先执行
1.I/O异常回调阶段
2.空闲预备阶段
2.poll轮询阶段 异步操作完了通知js主线程 如果有到时间的回到timmer阶段,执行完之后查看回调函数队列,有则check阶段,没有则等一会
3.check阶段
3.关闭事件的回调阶段
规则
1.process.nextTick()属于idle观察者,setImmediate()属于check观察者.在每一轮循环检查中,idle观察者先于I/O观察者,I/O观察者先于check观察者.
2.node 版本小于 11 的情况下,对于定时器的处理是:
若第一个定时器任务出队并执行完,发现队首的任务仍然是一个定时器,那么就将微任务暂时保存,直接去执行新的定时器任务,当新的定时器任务执行完后,再一一执行中途产生的微任务。
例题
题目一
题目
const promise1 = new Promise((resolve, reject) => {
console.log('promise1')
resolve('resolve1')
})
const promise2 = promise1.then(res => {
console.log(res)
})
console.log('1', promise1);
console.log('2', promise2);
答案
'promise1'
'1' Promise{<resolved>: 'resolve1'}
'2' Promise{<pending>}
'resolve1'
分析
- 从上至下,先遇到new Promise,执行该构造函数中的代码promise1
- 碰到resolve函数, 将promise1的状态改变为resolved, 并将结果保存下来
- 碰到promise1.then这个微任务,将它放入微任务队列
- promise2是一个新的状态为pending的Promise
- 执行同步代码1, 同时打印出promise1的状态是resolved
- 执行同步代码2,同时打印出promise2的状态是pending
- 宏任务执行完毕,查找微任务队列,发现promise1.then这个微任务且状态为resolved,执行它。
题目二
题目
setTimeout(() => {
console.log('timer1');
setTimeout(() => {
console.log('timer3')
}, 0)
}, 0)
setTimeout(() => {
console.log('timer2')
}, 0)
console.log('start')
setTimeout(() => {
console.log('timer1');
Promise.resolve().then(() => {
console.log('promise')
})
}, 0)
setTimeout(() => {
console.log('timer2')
}, 0)
console.log('start')
答案
'start'
'timer1'
'timer2'
'timer3'
'start'
'timer1'
'promise'
'timer2'
分析
这两个例子,看着好像只是把第一个定时器中的内容换了一下而已。
一个是为定时器timer3,一个是为Promise.then
但是如果是定时器timer3的话,它会在timer2后执行,而Promise.then却是在timer2之前执行。
你可以这样理解,Promise.then是微任务,它会被加入到本轮中的微任务列表,而定时器timer3是宏任务,它会被加入到下一轮的宏任务中。
题目三
题目
Promise.resolve().then(() => {
console.log('promise1');
const timer2 = setTimeout(() => {
console.log('timer2')
}, 0)
});
const timer1 = setTimeout(() => {
console.log('timer1')
Promise.resolve().then(() => {
console.log('promise2')
})
}, 0)
console.log('start');
答案
'start'
'promise1'
'timer1'
'promise2'
'timer2'