js事件队列(event-loop)宏任务、微任务

# 为什么要有事件循环呢?

event loop顾名思义就是事件循环,为什么要有事件循环呢?因为V8是单线程的,即同一时间只能干一件事情,但是呢文件的读取,网络的IO处理是很缓慢的,并且是不确定的,如果同步等待它们响应,那么用户就起飞了。于是我们就把这个事件加入到一个 事件队列里(task),等到事件完成时,event loop再执行一个事件队列。

 

所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不立即进入主线程、而先进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

 

任务队列:

"任务队列"是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。任务队列又分为宏队列和微队列,分别存放宏任务和微任务。

 

宏任务和微任务:

在JavaScript中,任务被分为两种,一种宏任务(MacroTask),一种叫微任务(MicroTask)。

常见的宏任务:

script全部代码、setTimeout、setInterval

常见的微任务:

Promise中then的回调函数、MutationObserver、Process.nextTick

(1)js代码执行时,先按代码顺序将同步任务压入主执行栈中执行

(2)遇到异步任务则先将异步任务压入对应的任务队列中(宏队列或微队列)

(3)同步任务执行完毕后,查看微队列,将微任务一一取出进入主执行栈中执行

(4)微任务队列清空后,再查看宏队列,只取出第一个宏任务执行,执行完一个宏任务后,回到第三步的操作

  这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。

(需要注意的点就是then中的回调函数要确定Promise状态后才能压入微队列)


 

// Promise中的执行顺序

let promise = new Promise(function(resolve, reject) {
    console.log('Promise');
    resolve();
});

promise.then(function() {
    console.log('resolved');
});

console.log('Hi!');//Promise//Hi! //resolved
setTimeout(function () {
    console.log(1);
    
});
new Promise(function(resolve,reject){
    console.log(2)
    resolve(3);

}).then(function(val){
    console.log(val);

    new Promise((resolve, reject) => {
        console.log(5)
        resolve(7)
    }).then(res => {
        console.log(res);
    })

})
console.log(4);
    
//先按顺序执行同步任务,
//Promise新建后立即执行输出2,接着输出4,异步任务等同步任务执行完后执行,
//且同一次事件循环中,微任务永远在宏任务之前执行。这时候执行栈空了,执行事件队列,
// 先取出微任务,输出3,最后取出一个宏任务,输出1。
    
console.log(1);
setTimeout(() => {
    console.log(2);
    Promise.resolve().then(() => {
        console.log(3);
    })
    console.log(8);
})
new Promise((resolve, reject) => {
    console.log(4);
    resolve(5);
}).then((data) => {
    console.log(data);
})
setTimeout(() => {
    console.log(6);
})
console.log(7)
// 1 4 7 5 2 8 3 6

 

console.log('1主线程');					//整体script作为第一个宏任务进入主线程
setTimeout(function() {				//setTimeout,其回调函数被分发到宏任务Event Queue(执行规则:从上到下排序,先进先执行)中
    console.log('2宏任务');
    process.nextTick(function() {
        console.log('3宏任务里面的微任务');
    })
    new Promise(function(resolve) {
        console.log('4微任务');
        resolve();
    }).then(function() {
        console.log('5微任务')
    })
})
process.nextTick(function() {	//process.nextTick()其回调函数被分发到微任务Event Queue中
    console.log('6微任务');
})
new Promise(function(resolve) {		//Promise,new Promise直接执行,输出7
    console.log('7微任务');
    resolve();
}).then(function() {
    console.log('8微任务')			//then被分发到微任务Event Queue中,排在process.nextTick微任务后面。
})
setTimeout(function() {			//setTimeout,其回调函数被分发到宏任务Event Queue中,排在前面的setTimeout后面
    console.log('9宏任务');
    process.nextTick(function() {
        console.log('10宏任务里面的微任务');
    })
    new Promise(function(resolve) {
        console.log('11微任务');
        resolve();
    }).then(function() {
        console.log('12微任务')
    })
})
 
//执行结果: 1主线程、7微任务、6微任务、8微任务、2宏任务、4微任务、3宏任务里面的微任务、5微任务、
//          9宏任务、11微任务、10宏任务里面的微任务、12微任务
// 先执行微任务、再执行宏任务

 

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值