我第一次看到他事件环(event-loop)的时候,我是一脸懵,这是什么鬼,是什么循环吗,为什么event还要loop,不是都是一次性的吗?

浏览器中和nodejs环境中的事件环是有一些区别的,这里我只研究了nodejs环境,小黑框情况下的事件环。

这里的事件环并不是指单独一件事件的循环,而是我们写的很多很多的事件按照一定地规则排着队去执行,然后队列清空后继续排队,就是事件环。

事件环很复杂,这里我只有能力解释事件环中的几个点:

node.js中对于事件环的解释

nodejs中将eventloop分成了:

  • timers: 定时器setTimeout执行,将callback加入队列中。
  • pending callbacks: 一些I/O的callback,推迟到下一次循环中执行。
  • idle, prepare: 内部的一些事件。
  • poll: 定时器的callback执行,setImmediate执行,微任务执行。
  • check: setImmediate的callback执行。
  • close callbacks: 一些callbacks的关闭,如socket。

这边我们专注于timers、poll和check这三个阶段。其他的我们用的不多。

timers、poll、check阶段

  • timers

这个阶段,只执行setTimeout和setInterval,但是他们的callback不会执行,而是推到宏任务的队列之中。

  • poll

这个阶段,会先执行符合条件的微任务,比如Promise的异步完成,如果是setImmediate,则只会执行,不执行他的callback,然后执行定时器的callback,比如timeout。这里会适当得暂停一会,看看会不会有新任务进入队列。如果有setImmediate的callback则进入check 阶段,否则回到timer继续新一轮循环。

  • check

当poll阶段的队列完成,则会轮到check,这时会执行setImmediate的callback。如果没有需要关闭callbacks,那么就回到timer继续新一轮的循环。

宏任务 vs 微任务

  • 宏任务

从我的角度理解,就是一个正常的task,本来在一个线程中可以毫无波折地一个接着一个运行到最后,奈何每个宏任务执行之后都有可能产生一些微任务,因此很不幸,这些宏任务就要排在这些微任务之后了。

宏任务代表:script(整体代码),setTimeout,setImmediate。

/**
output:
我先走一步
你太慢了,我插个队
老司机,等等我
*/
setTimeout(()=>{
console.log("我先走一步")
})
setTimeout(()=>{
console.log("老司机,等等我")
},10)
setImmediate(()=>{
console.log("你太慢了,我插个队")
})

划重点

setTimeout和setImmediate,触发的阶段不同,因此callback执行时间也不同。但是如果setTimeout的时间过长,那么系统会先执行setImmediate,然后等下一轮询中,如果setTimeout到时间了,那么就运行setTimeout的callbacks。

  • 微任务

就是宏任务执行时,产生的新的小任务,比如异步,此类任务称之为微任务,一般在当前宏任务执行完之后“插队”执行。

微任务代表:process.nextTick, Promise(原生)。

划重点

虽然process.nextTick和Promise都是微任务,但是他们的执行的先后顺序是不一样的。无论谁的代码先执行,等到了poll阶段,两者都是可运行的状态时,都是nextTick先于Promise执行。

/**
output:
本宫始终是你望成莫及的
总有一日,我会上位
*/
Promise.resolve().then(()=>{
console.log("总有一日,我会上位")
})
process.nextTick(()=>{
console.log("本宫始终是你望成莫及的")
})

后记:

我只写了我对于eventloop的理解,但是还有很多云里雾里的地方,写出来的只是我理解的。

最新文章

  1. CSS3简易表盘时钟
  2. ssh默认端口更改后,如何正常使用git?
  3. BZOJ1798: [Ahoi2009]Seq 维护序列seq
  4. 微信sdk分享,苹果手机分享到qq好友和qq空间没有反应
  5. NSIS打包(二)第一个安装包
  6. RxJava + Retrofit 的实际应用场景
  7. C#获取文件的当前路径
  8. mysql 的replace 和replace in to
  9. 局部敏感哈希-Locality Sensitive Hashing
  10. Head First C 笔记
  11. AP INVOICES IMPORT API(NOT request)
  12. springmvc简单的流程说明及源码分析
  13. vue 版本升级配置修改
  14. caffe编译环境的错误:..build_release/src/caffe/proto/caffe.pb.h:23:35: fatal error: google/protobuf/arena.h: 没有那个文件
  15. ASCII码,utf-8
  16. python中的popitem
  17. Spring加载properties文件的两种方式
  18. BZOJ 1412 [ZJOI2009]狼和羊的故事 | 网络流
  19. c 预处理的宏定义
  20. mysql-master-ha 实现mysql master的高可用。

热门文章

  1. [计算机]如何在win7下查看并更改文件的默认后缀名
  2. .net 接收存储过程的返回值 。。。。
  3. 配置Cocos Code IDE 可以正常运行的组合:jdk,sdk ,ndk, ant, cocos2d-x
  4. 4.4 Top-Down Parsing
  5. 移动前端第一弹:viewport详解
  6. 查看mysql数据库的所有配置信息和服务器的各种状态
  7. bzoj 1034: [ZJOI2008]泡泡堂BNB【贪心】
  8. bzoj 3942: [Usaco2015 Feb]Censoring【kmp+栈】
  9. bzoj 1690: [Usaco2007 Dec]奶牛的旅行【01分数规划+spfa】
  10. bzoj 1828: [Usaco2010 Mar]balloc 农场分配【贪心+线段树】