js事件循环机制(Event Loop)
javascript从诞生之日起就是一门 单线程的 非阻塞的 脚本语言,单线程意味着,javascript代码在执行的任何时候,都只有一个主线程来处理所有的任务,非阻塞靠的就是 event loop(事件循环),本文就讲解下事件循环。
event loop它最主要是分三部分:主线程、宏队列(macrotask)、微队列(microtask)
js的任务队列分为同步任务和异步任务,所有的同步任务都是在主线程里执行的,异步任务可能会在macrotask或者microtask里面
主线程
就是访问到的script标签里面包含的内容,或者是直接访问某一个js文件的时候,里面的可以在当前作用域直接执行的所有内容(执行的方法,new出来的对象等)
宏队列(macrotask)
setTimeout、setInterval、setImmediate、I/O、UI rendering
微队列(microtask)
promise.then、process.nextTick
执行顺序
1、先执行主线程
2、遇到宏队列(macrotask)放到宏队列(macrotask)
3、遇到微队列(microtask)放到微队列(microtask)
4、主线程执行完毕
5、执行微队列(microtask),微队列(microtask)执行完毕
6、执行一次宏队列(macrotask)中的一个任务,执行完毕
7、执行微队列(microtask),执行完毕
8、依次循环。。。
看下面代码练习练习
console.log(1)
process.nextTick(() => {
console.log(8)
setTimeout(() => {
console.log(9)
})
})
setTimeout(() => {
console.log(2)
new Promise(() => {
console.log(11)
})
})
requestIdleCallback(() => {
console.log(7)
})
// 特殊说明: new Promise()属于主线程任务
let promise = new Promise((resolve,reject) => {
setTimeout(() => {
console.log(10)
})
resolve()
// 这个console也属于主线程任务
console.log(4)
})
fn()
console.log(3)
promise.then(() => {
console.log(12)
})
function fn(){
console.log(6)
}
结果是1、4、6、3、12、8、2、11、10、9、7
这个写法可以囊括80%以上的event loop循环机制的场景了,下面开始梳理具体的运行机制。
js是从上到下执行的,所以上来先打印的是 1 ,继续往下走;
遇见了process.nextTick,因为它属于微队列(microtask),并且当前主线程的代码还没有执行完毕,所以它被展示扔到了微队列里,暂时不打印;
这个时候又遇到了setTimeout,setTimeout是属于宏队列(macrotask);
requestIdleCallback,这里也是不立即执行的,它也不属于任何队列,这里不做详细解释;
promise在实例化的时候,这里的setTimeout继续被丢到了宏队列(macrotask)中,并执行了成功的方法,在有promise.then的调用的时候就会去出发,但这里不做打印,接着发现了console,这里直接打印 4 );
fn函数直接调用,直接打印 6 ;
console,直接打印 3 ;
promise.then因为它属于微队列,但是它在promise实例化的时候被调用了,所以它会在微队列的最前面执行;
到这里主线程里面就没有任何可以执行到东西了,下面开始走微队列(microtask):
由于promise.then被提前调用了,所以它会先执行,打印 12 ;
微队列(microtask)里面还有一个,就是上面的process.nextTick,执行它,打印 8 ,这个时候发现它有一个setTimeout,放到宏队列(macrotask);
到这里微队列就走完了,下面开始走宏队列(macrotask):
最外面的setTimeout在一开始的时候被放了进去,所以先执行它,打印 2 ,发现它里面有promise被实例化,直接执行,打印 11 ;
下一个要走的就是promise里面的setTimeout,打印 10 ;
还剩最后一个setTimeout,就是process.nextTick里面的,打印 9 ;
到这里主线程、宏队列(macrotask)、微队列(microtask)就全都跑完了,在全部跑完的时候,requestIdleCallback才会执行,打印 7 ;
requesIdleCallback会在当前浏览器空闲时期去依次执行,在整个过程当中你可能添加了多个requestIdleCallback,但是都不会执行,只会在空闲时期,去依次根据调用的顺序就执行。
js事件循环机制(Event Loop)的更多相关文章
- Node.js 事件循环(Event Loop)介绍
Node.js 事件循环(Event Loop)介绍 JavaScript是一种单线程运行但又绝不会阻塞的语言,其实现非阻塞的关键是“事件循环”和“回调机制”.Node.js在JavaScript的基 ...
- 一篇文章图文并茂地带你轻松学完 JavaScript 事件循环机制(event loop)
JavaScript 事件循环机制 (event loop) 本篇文章已经默认你有了基础的 ES6 和 javascript语法 知识. 本篇文章比较细致,如果已经对同步异步,单线程等概念比较熟悉的读 ...
- js高级-浏览器事件循环机制Event Loop
JavaScript 是队列的形式一个个执行的 同一时间只能执行一段代码,单线程的 (队列的数据结构) 浏览器是多线程的 JavaScript执行线程负责执行js代码 UI线程负责UI展示的 Jav ...
- 理解js事件循环(event loop)
队列:先进先出 栈:后进先出 javascript的Event Loop 和 Node.js的Event Loop 区别: js(运行在浏览器),有主线程.异步任务队列的概念: node.js使用li ...
- 初探nodejs事件循环机制event loop
nodejs的特点 nodejs 具有事件驱动和非阻塞I/O的特点. 事件驱动是指nodejs把每一个任务当成事件来处理. 非阻塞I/O是指nodejs遇到I/O任务时,会从线程池调度单独的线程处理I ...
- js事件循环(event loop)
我们都知道,js是单线程的,虽然现在有 worker 的存在,但是也只是可以进行运算,并不能操作 dom: js最一开始执行的线程,是主线程,然后主线程执行完毕后,是微队列 microtask 的循环 ...
- 关于事件循环机制event loop
setTimeout(()=> { console.log('settimeout') },100) console.log('开始') console.log('结束') new Promis ...
- 深入理解JavaScript的事件循环(Event Loop)
一.什么是事件循环 JS的代码执行是基于一种事件循环的机制,之所以称作事件循环,MDN给出的解释为 因为它经常被用于类似如下的方式来实现 while (queue.waitForMessage()) ...
- js事件循环机制辨析
对于新接触js语言的人来说,最令人困惑的大概就是事件循环机制了.最开始这也困惑了我好久,花了我几个月时间通过书本,打代码,查阅资料不停地渐进地理解他.接下来我想要和大家分享一下,虽然可能有些许错误的 ...
随机推荐
- DRUPAL性能优化【转】
1.启用memcache代替Mysql的缓存表处理缓存数据. 2.添加一个opcode缓存可以让 PHP能够重用前面编译过的代码,这样就会跳过解析和编译.常见的opcode缓存有Alternative ...
- (五)Lucene——中文分词器
1. 什么是中文分词器 对于英文,是安装空格.标点符号进行分词 对于中文,应该安装具体的词来分,中文分词就是将词,切分成一个个有意义的词. 比如:“我的中国人”,分词:我.的.中国.中国人.国人. 2 ...
- C#7.0之元组数据
static (string,string,string) LookupName(int a) { return ("","",""); } ...
- IE6—在链接click事件的响应函数中发送jsonp请求不生效
$("#link").click(function(){ $.ajax({ type: 'GET', dataType: 'jsonp', ...
- 一个官翻教程集合:ASP.NET Core 和 EF Core 系列教程
通过一个大学课程案例讲解了复杂实体的创建过程及讲解 1.ASP.NET Core 和 Entity Framework Core 系列教程——入门 (1 / 10) 2.ASP.NET Core 和 ...
- WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!问题解决
用mac终端ssh连接Linux服务器,提示以下错误: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ WARNING: RE ...
- html5-本地数据库的操作
<script src="jquery-1.8.3.js"></script><script>/* IE11不支持此操作创建数据库 解释一下op ...
- php serialize序列化对象或者数组
serialize序列化对象或者数组 $str=serialize(array('a'=>1,'b'=>2)); echo $str; 输入出a:2:{s:1:"a"; ...
- sql自动增长标识(转载)
sql自动增长标识 对于一个设了自动增长标识的数据表来说,它的字段的值是由数据库自动设置的:这在导数据时很麻烦. 当我们导数据时,我们往往想想将标识字段的数据也导进来,怎么办呢? 方法有两 ...
- centos 安装cmake 3.3.2
先卸掉本身自带的 cmake 2.8 yum remove cmake cmake版本:3.3.2 安装编译源码所需的工具和库 yum install gcc gcc-c++ ncurses-deve ...