当前位置: 首页 > news >正文

理解javascript事件循环

1背景

从敲下第一行“Hello World!”起,我们都无时无刻的使用并接触着事件循环。

去年写react的时候总会遇到设置setState,后面调用值不会改变的问题。会想到是异步的原因,试着延时定时问题得到解决。

    this.setState({status: 1})
    console.log(this.state.status);   //0
    setTimeout(()=>{
        console.log(this.state.status);    //1
    },100)
复制代码

问题可以解决,所以延时定时解决了之后的很多问题。

后面看到javascript的事件循环,才真正理解了这之中的原理。

2单线程

从学习JavaScript开始,就一直看书和资料说JavaScript是一门单线程的语言。JavaScript到处存在着异步(刚开始认为异步是主线程下开的子线程)是依靠事件循环来实现的。

3同步异步

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。

如果计算量大,读写IO请求、Ajax开销大。如果通过同步来获取数据会造成程序阻塞。所以像这种开销大的任务,我们使用异步处理。

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

4事件循环

根据事件循环图来理解这一段代码

//首先整段代码进入主线程执行
let a= 5;
//同步代码立即执行,输出a=5
console.log(a);
//按钮绑定点击事件,当用户点击按钮事件回调函数进入任务队列,待主线程执行完毕调用该函数
oBtn.onclick(function () {
    a = 10;
    console.log(a, 'click');
})
//当延时定时时间到的时候,回调函数进入任务队列,待主线程执行完毕调用任务队列中的函数。
setTimeout(function () {
    console.log(a,'timeout');
},5000)
复制代码

5node中的事件循环

Node.js也是单线程的Event Loop,但是它的运行机制不同于浏览器环境。

  • V8引擎解析JavaScript脚本。
  • 解析后的代码,调用Node API。
  • libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Event Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎。
  • V8引擎再将结果返回给用户。

除了setTimeout和setInterval这两个方法,Node.js还提供了另外两个与"任务队列"有关的方法:process.nextTick和setImmediate。它们可以帮助我们加深对"任务队列"的理解。

process.nextTick方法可以在当前"执行栈"的尾部----下一次Event Loop(主线程读取"任务队列")之前----触发回调函数。也就是说,它指定的任务总是发生在所有异步任务之前。setImmediate方法则是在当前"任务队列"的尾部添加事件,也就是说,它指定的任务总是在下一次Event Loop时执行,这与setTimeout(fn, 0)很像。

process.nextTick(function A() {
  console.log(1);
  process.nextTick(function B(){console.log(2);});
});

setTimeout(function timeout() {
  console.log('TIMEOUT FIRED');
}, 0)
// 1
// 2
// TIMEOUT FIRED
复制代码

上面代码中,由于process.nextTick方法指定的回调函数,总是在当前"执行栈"的尾部触发,所以不仅函数A比setTimeout指定的回调函数timeout先执行,而且函数B也比timeout先执行。这说明,如果有多个process.nextTick语句(不管它们是否嵌套),将全部在当前"执行栈"执行。

现在,再看setImmediate。

setImmediate(function A() {
  console.log(1);
  setImmediate(function B(){console.log(2);});
});

setTimeout(function timeout() {
  console.log('TIMEOUT FIRED');
}, 0);
复制代码

哪个回调函数先执行呢?答案是不确定。运行结果可能是1--TIMEOUT FIRED--2,也可能是TIMEOUT FIRED--1--2。setImmediate与setTimeout不分伯仲。

但在递归中,setImmediate永远优于setTimeout

setImmediate(function (){
  setImmediate(function A() {
    console.log(1);
    setImmediate(function B(){console.log(2);});
  });

  setTimeout(function timeout() {
    console.log('TIMEOUT FIRED');
  }, 0);
});
// 1
// TIMEOUT FIRED
// 2
复制代码

最后感谢阮一峰老师的文章和张仁阳老师的思路。

相关文章:

  • Brup Suite 渗透测试笔记(五)
  • Java:枚举类enum
  • 数据库副本的自动种子设定(自增长)
  • Java入门篇(六)——类和对象
  • My year of 2017
  • 何玺:区块链的价值不止产比特币,在对未来商业逻辑的重构与创新
  • 5,元组
  • vue 前端上传图片组件
  • vuex 笔记整理
  • javascript 总结(常用工具类的封装)
  • 深入浅出webpack学习(1)--核心概念
  • Js基础知识(一) - 变量
  • Linux常用命令大全 (非常有用)
  • 配置karma支持Chrome浏览器
  • Java程序员升职加薪必备技术——分布式
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • 345-反转字符串中的元音字母
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • DOM的那些事
  • go append函数以及写入
  • HomeBrew常规使用教程
  • log4j2输出到kafka
  • Transformer-XL: Unleashing the Potential of Attention Models
  • 阿里研究院入选中国企业智库系统影响力榜
  • 电商搜索引擎的架构设计和性能优化
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 理解在java “”i=i++;”所发生的事情
  • 使用Maven插件构建SpringBoot项目,生成Docker镜像push到DockerHub上
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 找一份好的前端工作,起点很重要
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • # 安徽锐锋科技IDMS系统简介
  • #LLM入门|Prompt#2.3_对查询任务进行分类|意图分析_Classification
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • (day 12)JavaScript学习笔记(数组3)
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (附源码)计算机毕业设计高校学生选课系统
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (三)elasticsearch 源码之启动流程分析
  • (十二)python网络爬虫(理论+实战)——实战:使用BeautfulSoup解析baidu热搜新闻数据
  • (未解决)jmeter报错之“请在微信客户端打开链接”
  • (转)Linux下编译安装log4cxx
  • (转)负载均衡,回话保持,cookie
  • (转)关于多人操作数据的处理策略
  • ./和../以及/和~之间的区别
  • .chm格式文件如何阅读
  • .NET框架
  • .Net面试题4
  • .NET中的Event与Delegates,从Publisher到Subscriber的衔接!
  • ??myeclipse+tomcat
  • [2013][note]通过石墨烯调谐用于开关、传感的动态可重构Fano超——
  • [Android]竖直滑动选择器WheelView的实现
  • [AutoSar]工程中的cpuload陷阱(三)测试