参考博文
为什么有事件循环
js是运行于浏览器的脚本语言,因其经常涉及操作dom,如果是多线程的,如果一个线程修改dom,另一个线程删除dom,那么浏览器就不知道该先执行哪个操作,所以js执行的时候会按照一个任务一个任务来执行,那么任务是怎么排列的呢
JS任务分为同步任务和异步任务。试想一下,如果js的任务都是同步的,那么遇到定时器、网络请求等这类型需要延时执行回调函数的任务会发生什么?页面会像瘫痪一下暂停下来等待这些需要需要时间的代码执行完毕,基于此,又引入了异步任务。异步任务分为宏任务和微任务。
- 同步任务:同步任务不需要进行等待可立即看到执行结果,比如console
- 异步任务:异步任务需要等待一定的时候才能看到结果,比如setTimeout、网络请求
为什么异步任务的事件中要区分宏任务和微任务
假设如果异步任务的回调是在操作dom,但是页面渲染也是一个任务,如果把dom渲染的任务排到异步任务的队尾,那么页面同样会出现瘫痪,所以js就规定一些可以插队完成的任务,这类型的任务称为微任务,比如说dom渲染,后面又引入promise.then。
在JS中宏任务队列只有一个,而每一个宏任务都有一个自己的微任务队列,每轮循环都是由一个宏任务+多个微任务组成。微任务是在执行宏任务的过程中产生的,因此每一个宏任务都对应着一个微任务队列。微任务队列可为空,即该宏任务执行过程中没有产生微任务。
宏任务和微任务有哪些,他们之间的优先级是什么
常见的宏任务有:
script(整体代码)
setTimout
setInterval
setImmediate(node 独有)
requestAnimationFrame(浏览器独有)
IO/UI render(浏览器独有)
网络请求
new Promise(xxx)中xxx是同步代码
常见的微任务有:
process.nextTick(node 独有)
Promise.then()
Object.observe
MutationObserver
async
应注意的:
1、new Promise(xxx)中xxx是立即执行的(示例1)
2、在async/await中,在出现await出现之前,其中的代码也是立即执行的,
await XXX;中的 XXX 也是立即执行的,await XXX;之后的语句会被添加到微任务队列中。(示例1)
3、微任务队列中 process.nextTick的优先级最高(示例1)
4、宏任务队列中 setTimeout 比 setImmediate 优先级更高(示例2)
5、宏任务队列中 setTimeout 的执行优先级与其设置的时间有关(示例3)
6、宏任务队列中,若设置时间都为默认时间,则优先级顺序为:
setTimeout/setInterval > IO/UI render(浏览器独有)> setImmediate(node 独有)
JS的执行顺序如何描述
1、将整个JS代码放入执行栈中,此时可将整个JS代码视为宏任务队列中第一个宏任务,也是唯一一个宏任务。
且在未开始执行时,微任务队列为空。
2、开始执行当前宏任务,执行过程中,同步任务自上而下依次执行,
异步任务中的宏任务被添加到宏任务队列(不一定放在队尾),微任务则被添加到微任务队列(不一定放在队尾)
3、执行完当前宏任务后,会在其对应的微任务队列中取出队首的微任务;
4、若执行微任务的过程中产生了宏任务,则会将产生的宏任务放入宏任务队列中(不一定放在队尾)
5、执行完当前微任务后,会接着去取微任务队列中的微任务,直到此微任务队列为空,则完成一次事件循环。
6、若宏任务队列不为空,则取出队首的宏任务,重复2-5的操作,直至宏任务队列为空。
示例1
async function fn() {
console.log(1);
await console.log(2);
console.log(3);
}
fn()
new Promise(resolve => {
console.log(4)
resolve()
console.log(5)
}).then(() => {
console.log(6)
})
process.nextTick(() => {
console.log(7)
})
// 输出 1 2 4 5 7 3 6
示例2
setTimeout(() => {
console.log('setTimeout')
})
setImmediate(() => {
console.log('setImmediate')
})
//输出 setTimeout setImmediate
示例3
//微任务产生的不同宏任务的优先级
new Promise(resolve => { // 第二个promise
console.log(1)
resolve()
}).then(function() {
setTimeout(() => {
console.log(2)
}, 4000)
}).then(function() {
setTimeout(() => {
console.log(3)
}, 2000)
}).then(function() {
setTimeout(() => {
console.log(4)
}, 1000)
})```
//输出 1 4 3 2
原文地址:https://www.jb51.cc/wenti/3282202.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。