[JavaScript]js EventLoop And Async

本文解析了JavaScript的事件循环机制,包括其工作原理、为什么需要事件循环、事件循环的简单流程及任务优先级等内容,并通过示例代码说明了宏任务与微任务的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

What

js事件循环

先来看一张图(这张图来自于http://www.zcfy.cc/article/node-js-at-scale-understanding-the-node-js-event-loop-risingstack-1652.html)


再来看一张图(这张图来自于https://www.cnblogs.com/hity-tt/p/6733062.html)


从一开始,js有一个执行栈(stack)中存放了该页面所有的代码即该页面主线程,当执行遇到异步操作(async)时,浏览器的webcore模块(如network,timer,domBinding模块等)将其放置到一个幕后线程中等待,然后浏览器接着执行主线程,当幕后线程中的代码准备好了(如定期器时间到了,请求的响应来了),该线程就会把这个函数的回调放到taskQueue(任务队列)中等待,当主线程的执行栈全部执行完毕时(所有同步操作全部执行完毕),主线程对任务对列进行检测是否有任务要执行,如果有,就把该任务放到执行栈中进行,如果没有,就保持等待(循环检测)任务到来。

上述的过程,就是事件循环(EventLoop)。

Why need EventLoop 

因为web前端端用户的丰富交互性问题,js这边采取了单线程来应对多个交互产生时的程序操作复杂性问题。由于单线程的出现,当同步操作出现长时间等待时就会出现线程阻塞,为了解决阻塞,出现了异步操作(变相多线程)来解决线程阻塞。

异步操作就是通过EventLoop的实现的

SimpleLook

事件循环三步看

  1.  判断js代码是否为异步,异步则放置该代码到幕后线程,同步则继续执行
  2.  幕后线程中的函数回调被触发时将该代码推入任务队列
  3.  同步任务执行完毕后,检测事件队列,将任务队列尾部函数回调推入执行栈执行
  4.  以上三步循环执行,即EventLoop

两步来看

  1. 执行主线程,同步操作,遇到异步压入事件表随后(该代码在触发响应时)压入队列
  2. 主线程代码执行完毕后,无限循环(?)检测异步事件队列,有则进入1执行

一句话讲清楚

主线程执行完毕后,检测任务队列有则取出一个插入主线程,重复该动作。

任务优先级

如上图,任务队列中的任务分为两种,对应大型工作场景和微处理场景,即对应的传说中的Macrotask和Microtask。

what

顾名思义,即多个任务同时出现时的执行优先等级。

Macrotask: setTimeout,setInterval,用户交互操作/UI渲染(请求回调执行)etc

Microtask:  Promise,process.nextTick(nodejs) etc

why

当任务队列中有多个任务时,事件优先级就需要出现了。

How

大致多任务时处理步骤如下四小步(来自网上,感觉该步骤描述有问题)

1. 检测Macrotask,空3,非空2

2. 从Macrotask队列中取队首(在队列时间最长)的任务进去执行栈中执行(仅仅一个),执行完后进入下一步

3. 检查Microtask队列是否为空,若不为空,则4,否则,跳到1(开始新的事件循环)

4. 从Microtask队列中取队首(在队列时间最长?)的任务进去事件队列执行,执行完后,跳到3


简而言之:同步环境执行 -> 事件循环1(microtask queue的All)-> 事件循环2(macrotask queue中的一个) -> 事件循环1(microtask queue的All)-> 事件循环2(macrotask queue中的一个)...


Demo

demo来源于网上,做抽象概念具现化理解用

setTimeout(function(){console.log('111')},0);
new Promise(function(resolve,reject){
console.log("2222");//此处还没有执行异步操作,执行异步操作及执行回调函数,在promise中即then中的回调
resolve();
}).then(function(){console.log('3333')})
console.log("44444");
//输出
// 2222
// 44444//上面的两个输出属于同步操作
// 3333//promise加入到队列的优先级高于setTimeout
//111

嵌套微任务

new Promise(function(resolve,reject){

resolve();
}).then(function(){
console.log("111");
return new Promise(function(resolve,reject){
resolve();
})
}).then(function(){ console.log("222");})
new Promise( function(resolve,reject){
resolve();
}).then(function(){ console.log("33333");})
//输出
111 33333 222


Last,如果觉得总结的对你的理解有点帮助,请帮忙点个赞吧!!(给您鼓掌h0h)

如果写的有不对的地方,请您评论留言!谢谢^_^


转载于:https://juejin.im/post/5ca0d248e51d4556971614aa

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值