1- JS是单线程语言
2- JS的 Event Loop 是JS的执行机制。深入了解JS的执行,就等于深入了解JS里的 event loop
场景描述:
现在有2个线程,process1 process2,由于是多线程的JS,所以他们对同一个dom,同时进行操作
process1 删除了该dom,而process2 编辑了该dom,同时下达2个矛盾的命令,浏览器究竟该如何执行呢?
场景描述:
如果JS中不存在异步,只能自上而下执行,如果上一行解析时间很长,那么下面的代码就会被阻塞。
对于用户而言,阻塞就意味着"卡死",这样就导致了很差的用户体验
console.log(1)
setTimeout(function(){
console.log(3)
},0)
console.log(2)
//执行结果 1 2 3
也就是说,setTimeout里的函数并没有立即执行,而是延迟了一段时间,满足一定条件后,才去执行的,这类代码,我们叫异步代码。所以,这里我们首先知道了JS里的一种分类方式,就是将任务分为: 同步任务和异步任务
宏任务{ settimeout
setInterval
I/O 事件
UI交付事件
postMessage
MessageChannel
setImmediate
}
微任务{ Promise.then
Object.observe
MutaionObserver
process.nextTick(Node.js 环境)
}
执行流程图 1-首先执行script下的宏任务,
2-判断 js代码是同步 还是异步
3-同步会进入到主线程
4-异步加入到event table(事件表)
5-异步任务在event table中注册函数,当满足条件时,被退路 event queue(事件队列)
6-同步任务进入主线程的后会一直执行,直到主线程空闲时,
7-去任务队列中查看并以此执行的队列中的宏任务
setTimeout(_ => console.log(4))
new Promise(resolve => {
resolve()
console.log(1)
}).then(_ => {
console.log(3)
})
console.log(2)
来看看答案是否一致 :1,2,3,4
分析一下:
setTimeout
就是作为宏任务来存在的,而Promise.then
则是具有代表性的微任务,上述代码的执行顺序就是按照序号来输出的。所有会进入的异步都是指的事件回调中的那部分代码
也就是说new Promise
在实例化的过程中所执行的代码都是同步进行的,而then
中注册的回调才是异步执行的。
在同步代码执行完成后才回去检查是否有异步任务完成,并执行对应的回调,而微任务又会在宏任务之前执行。所以输出结果为1,2,3,4
setTimeout(_ => console.log(6), 5000)//创建宏任务
setTimeout(_ => console.log(4), 3000)//创建宏任务
new Promise(resolve => { //创建一个微任务
resolve()
console.log(1)
}).then(_ => {
console.log(3)
Promise.resolve().then(_ => {
console.log('before timeout')
setTimeout(() => { //增加宏任务
console.log(5);
}, 0);
for (let i = 0; i < 90; i++) {//增加一个微任务
if (i == 89) {
console.log(7);
}
}
}).then(_ => { //增加一个微任务
Promise.resolve().then(_ => {
console.log('also before timeout')
})
})
})
console.log(2)
1,2,3,before timeout,7,also before timeout,5,4,6
setTimeout(_ => console.log(6), 5000) :异步任务在event table中注册函数,当满足条件时,才会被推入 event queue(事件队列)
也是就说当5秒后才算是主线程空闲 才会将此条宏任务 推入事件队列
就说到这里吧 相比大家都有所收获, 觉得满意可以给博主点赞奥 记得加关注,或者留言,欢迎赐教...
转载请注明 原文地址...https://blog.csdn.net/mnilz/article/details/106431371