前言

  最近在准备春招,刷到了JS中的主要运行机制--Event Loop,觉得它的实现思路有必要整理一下,以防忘记。关于它在浏览器上的实现,我结合了自己的理解以及示例代码,想用最通俗的语言表达出来。如果在文中出现书写错误的地方,欢迎大家留言一起探讨。

正文

  关于Event Loop,宏任务,微任务的概念不再此赘述了。

概念

  进入主题,我理解的浏览器的事件循环Event Loop,以及执行一个JavaScript代码的流程如下:

  1. 一开始整段脚本作为第一个宏任务执行;
  2. 执行过程中同步代码直接执行,宏任务进入宏任务队列,微任务进入微任务队列;
  3. 当前宏任务执行完出队,检查微任务队列,如果有则依次执行,直到微任务队列为空;如果在执行微任务的过程中,又产生了微任务,那么会加入到队列的末尾,也会在这个周期被调用执行;
  4. 执行浏览器 UI 线程的渲染工作;
  5. 执行队首新的宏任务,回到2,依此循环,直到宏任务和微任务队列都为空。

代码

     console.log('start');

     setTimeout(() => {
console.log('timeout');
Promise.resolve().then(() => {
console.log('p1')
});
}); Promise.resolve().then(() => {
console.log('p2');
}); console.log('end'); new Promise((resolve, reject) => {
console.log('end2')
resolve('p3')
}).then((data) => {
console.log(data);
})
//输出结果为:

    start 
    end
    end2
    p2
    p3
    timeout
    p1

解析:

Step 1:执行全局Script代码

console.log('start');
//打印结果:start

  栈:[ console ]

  宏任务队列:[ ]

  微任务队列:[ ]

setTimeout(() => {
console.log('timeout');//将这个回调函数叫做callback1,由于setTimeout属于宏任务,所以放到宏任务队列
   Promise.resolve().then(() => {
console.log('p1')
});
}); //打印结果:start

  栈:[ setTimeout ]

  宏任务队列:[ callback1 ]

  微任务队列:[ ]

Promise.resolve().then(() => {
console.log('p2');  //将这个回调函数叫做callback2,由于Promise属于微任务,所以放到微任务队列
}); //打印结果:start

  栈:[ Promise ]

  宏任务队列:[ callback1 ]

  微任务队列:[ callback2 ]

console.log('end');

/*
打印结果:start
        end
*/

  栈:[ console ]

  宏任务队列:[ callback1 ]

  微任务队列:[ callback2 ]

 new Promise((resolve, reject) => {
console.log('end2')  //注意,这里是同步执行的!!!
resolve('p3')  //将这个回调函数叫做callback3,由于Promise属于微任务,所以放到微任务队列
}).then((data) => {
console.log(data);
}) /*
打印结果: start
         end
         end2
*/

  栈:[ Promise ]

  宏任务队列:[ callback1 ]

  微任务队列:[ callback2 callback3 ]

Step 2:全局Script代码执行完成,进入微任务队列,取出任务并执行,直至微任务队列为空。

  微任务队列:[ callback2 callback3 ]

  1.首先执行callback2任务:

Promise.resolve().then(() => {
console.log('p2');  //将这个回调函数叫做callback2
}); //打印结果:start
      end
      end2
      p2

  栈:[ callback2 ]

  宏任务队列:[ callback1 ]

  微任务队列:[ callback3 ] 

  2.其次执行callback3任务:

 new Promise((resolve, reject) => {
console.log('end2')  //注意,这里是同步执行的
resolve('p3')  //将这个回调函数叫做callback3
}).then((data) => {
console.log(data);
}) /*
打印结果:start
       end
       end2
       p2
       p3
*/

  栈:[ callback3 ]

  宏任务队列:[ callback1 ]

  微任务队列:[ ] 

Step3:微任务队列全部执行完,再去宏任务队列中取第一个任务执行。

setTimeout(() => {
console.log('timeout');  //将这个回调函数叫做callback1
   Promise.resolve().then(() => {
console.log('p1')    //将这个回调函数叫做callback4
});
});
//打印结果:start
       end
       end2
       p2
       p3
       timeout

【注】:当执行callback1的时候又遇到了另一个promise,promise异步执行完后在微任务队列中又注册了一个callback4回调函数。

  栈:[ callback1 ]

  宏任务队列:[ ]

  微任务队列:[ callback4 ] 

Step4:当前宏任务执行完出队,检查微任务队列

setTimeout(() => {
console.log('timeout');  
   Promise.resolve().then(() => {
console.log('p1')    //将这个回调函数叫做callback4
});
}); /*
打印结果:start
       end
       end2
       p2
       p3
       timeout
p1
*/

  栈:[ callback4 ]

  宏任务队列:[ ]

  微任务队列:[ ]

至此,执行完毕。

尾声

以上就是我分析的浏览器篇Event Loop的一个例子,如有错误,还请指正,谢谢!希望本次分享对你有用呀 ^_^

如何理解EventLoop--浏览器篇的更多相关文章

  1. 我是这样理解EventLoop的

    我是这样理解EventLoop的 一.前言   众所周知,在使用javascript时,经常需要考虑程序中存在异步的情况,如果对异步考虑不周,很容易在开发中出现技术错误和业务错误.作为一名合格的jav ...

  2. [Web] 深入理解现代浏览器

    转载: https://blog.csdn.net/qihoo_tech/article/details/91921777 奇技指南 身为前端,你真正深入理解了浏览器吗? 本文来自公众号奇舞周刊,作者 ...

  3. C#串口通讯教程 简化一切 只保留核心功能 这可能是最易于理解的一篇教程

    C#串口通讯教程 简化一切 只保留核心功能 这可能是最易于理解的一篇教程   串口的定义,请自行了解. C#操作串口通讯在.Net强大类库的支持下,只需要三个步骤: 1 创建 2 打开 3 发送/接受 ...

  4. 前端面试总结——http、html和浏览器篇

    1.http和https https的SSL加密是在传输层实现的. (1)http和https的基本概念 http: 超文本传输协议,是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和 ...

  5. iOS开发:深入理解GCD 第一篇

    最近把其他书籍都放下了,主要是在研究GCD.如果是为了工作,以我以前所学的GCD.NSOperation等知识已经足够用了,但学习并不仅仅知识满足于用它,要知其然.并且知其所以然,这样才可以不断的提高 ...

  6. 15分钟理解HTTPS——通俗篇

    | 导语 它很深奥吗?你肯定常常见过它,使用它,甚至离不开它... 它很浅显吗?你可能觉得看透它,理解它,甚至懂它... 让我们用15分钟,不那么学术地将它的深挖到底~ 什么?如何证明我是我?本文要上 ...

  7. 理解 EventLoop

    链接 链接 node 浏览器 执行顺序有差异 macrotask microtask 一个线程会有 堆 栈 消息队列;  栈函数执行是用的, 堆用了存放定义的对象, 消息队列来处理异步的操作 a() ...

  8. 理解http浏览器的协商缓存和强制缓存

    阅读目录 一:浏览器缓存的作用是什么? 二:理解协商缓存 1 Last-Modified/if-Modify-Since 2 ETag/if-None-Match 三:理解强制缓存 回到顶部 一:浏览 ...

  9. Range对象理解,浏览器兼容性,获取鼠标光标位置

    一.关于浏览器的兼容性 目前主要有3种关于range的类似的对象,分别是W3C range 对象,Mozzlia selection ,ie TextRange 关于这三种的区别,请查看文档 http ...

  10. iOS开发:深入理解GCD 第二篇(dispatch_group、dispatch_barrier、基于线程安全的多读单写)

    Dispatch Group在追加到Dispatch Queue中的多个任务处理完毕之后想执行结束处理,这种需求会经常出现.如果只是使用一个Serial Dispatch Queue(串行队列)时,只 ...

随机推荐

  1. 使用 custom element 创建自定义元素

    很早我们就可以在 HTML 文档中写 <custome-element></custom-element> 这样的自定义名称标签.但是浏览器对于不认识的标签一律当成一个普通的行 ...

  2. 盒马微信小程序

    盒马app刚出现,就吸足了眼球.最近看了看盒马界面,很Q,就想着仿照app写个小程序. 功能介绍 好奇微信小程序是如何制作的,也对盒马app感兴趣,就尝试写了这个盒马小程序.实现了app的部分功能,还 ...

  3. 前端实现html转pdf方法总结

    最近要搞前端html转pdf的功能.折腾了两天,略有所收,踩了一些坑,所以做些记录,为后来的兄弟做些提示,也算是回馈社区.经过一番调(sou)研(suo)发现html导出pdf一般有这几种方式,各有各 ...

  4. 【Geek议题】合理的VueSPA架构讨论(上)

    前言 web前端发展到现代,已经不再是严格意义上的后端MVC的V层,它越来越向类似客户端开发的方向发展,已独立拥有了自己的MVVM设计模型.前后端的分离也使前端人员拥有更大的自由,可以独立设计客户端部 ...

  5. python框架Django实战商城项目之工程搭建

    项目说明 该电商项目类似于京东商城,主要模块有验证.用户.第三方登录.首页广告.商品.购物车.订单.支付以及后台管理系统. 项目开发模式采用前后端不分离的模式,为了提高搜索引擎排名,页面整体刷新采用j ...

  6. 没想到MySQL还会问这些...

    前言 文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y 在前一阵子,大哥问过我:"你知道MySQL的原子性是怎么保 ...

  7. webpack进阶(三)

    1)CommonsChunkPlugin已经从webpack4移除,所以在用webpack进行公共模块的拆分时,会报错 Cannot read property 'CommonsChunkPlugin ...

  8. JavaScript对象(三)

    序列化对象: 对象序列化:对象的状态转化为字符串,也可以将字符串还原为对象.方法:JSON.stringify(),用来序列化,JSON.parse(),用来还原对象. JSON(JavaScript ...

  9. Druid未授权(弱口令)的一些利用方式

    Druid简介 1.Druid是阿里巴巴数据库事业部出品,为监控而生的数据库连接池. 2.Druid提供的监控功能,监控SQL的执行时间.监控Web URI的请求.Session监控. Druid可能 ...

  10. 编译putty 源码去掉 Are you sure you want to close this session? 提示

    0, 为什么要编译 putty ?在关闭窗口的时候,会弹出一个 Are you sure you want to close this session?要把这个去掉.当然也可以用 OD 之类的来修改. ...