JS事件环EventLoop的理解

JS事件环EventLoop的理解

本文的详解主要是自己总结,对EventLoop的理解。

关于javascript

javascript是一门单线程语言,在最新的HTML5中提出了Web-Worker,但javascript是单线程这一核心仍未改变。所以一切javascript版的"多线程"都是用单线程模拟出来的,一切javascript多线程都是纸老虎!

javascript事件循环

既然js是单线程,那就像只有一个窗口的银行,客户需要排队一个一个办理业务,同理js任务也要一个一个顺序执行。如果一个任务耗时过长,那么后一个任务也必须等着。那么问题来了,假如我们想浏览新闻,但是新闻包含的超清图片加载很慢,难道我们的网页要一直卡着直到图片完全显示出来?所以将程序任务分为两类:分别是同步任务和异步任务。

在JS的执行栈中,同步任务进入主执行栈(也可以说主线程),而异步任务进入任务队列(TaskQueue)等待执行,任务队列可以理解成一个消息队列,I/O设备完成一件事,就向任务队列添加一个事件,一旦主执行栈中所有的同步任务执行完毕,就会读取任务队列中等待的任务,并放入执行栈开始执行,其实就是执行异步任务的回调函数,所以说异步任务必须指定回调函数,主线程会不断的循环这个动作,所以这种运行机制又称为EventLoop(事件循环)。( 这里解释一下什么叫‘任务队列’:这是一个先进先出的数据结构,排在前面的事件会优先被主线程读取,但是当有定时器的时候主线程会先检查一下执行时间。)我们画一张图来理解这个:

  • 从上面图中看到其中有宏任务和微任务

宏任务(MacroTask):setTimeout,setInterval,setImmediate(只兼容ie)

微任务(MicroTask):Promise,vue.$nextTick(function(){})

那接下来看一段代码:

console.log('main1');  
process.nextTick(function() {  
    console.log('process.nextTick1');  
});  
setTimeout(function() {  
    console.log('setTimeout');  
    process.nextTick(function() {  
        console.log('process.nextTick2');  
    });  
}, 0);  
new Promise(function(resolve, reject) {  
    console.log('promise');  
    resolve();  
}).then(function() {  
    console.log('promise then');  
});  
console.log('main2');  
复制代码

JS代码开始从上往下单线程执行:

1.console.log('main1');进入执行栈执行;

2.遇到process.nextTick将它的回调函数先放入MicroTask(微任务);

3.遇到setTimeout将它的回调函数放入MacroTask(宏任务队列);

4.在执行栈中new Promise并将.then中注册的回调放入MicroTask(微任务);

5.最后一行代码console.log('main2');会放入主执行栈执行.综上所述,这段代码的结果就是先输出main1,然后第二步第三步我们不用管它,它不是在主执行栈中,所以直接到第四步输出promise,然后主执行栈继续执行第五步输出main2。

此时主执行栈执行完毕,开始事件循环,发现在MicroTask中还有任务,开始清空微任务,第二步中我们在微任务中放入了process.nextTick所以输出process.nextTick1,在第四步中将.then的回调放入了微任务,那么微任务队列继续执行输出promise then,此时微任务队列已经清空开始事件循环宏任务队列,也就是输出第三步中的setTimeout,在输出之后发现setTimeout这个回调中还有一个process.nextTick,那么这个回调继续放入微任务队列,此时事件循环发现主执行栈中已经没有任务,那么开始执行MicroTask输出:process.nextTick2

所以这道题的答案是: //main1 promise main2 process.nextTick1 promise then setTimeout process.nextTick2

在这道题中在主进程执行完毕后,应该会调用任务队列的宏任务,但是在这之前要清空了MicorTask微任务,这与我们先说的一次事件循环的循环机制(先读取宏任务后读取微任务)相悖,所以说主进程的代码也是一个MacroTask(参考:Promises/A+规范,也就是说执行完主进程的代码后执行MicroTask这是第一个事件循环(event loop),然后又开始执行任务队列(MacroTask)和process.nextTick2属于第二个事件循环。

下图为此题分析图:

来源参考:https://blog.csdn.net/yangbo1993/article/details/79114909

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值