javascript是一门单线程的非阻塞的脚本语言。单线程意味着javascript在执行代码的任何时候,都只有一个主线程来处理所有的任务。非阻塞:是当代码需要进行一项异步任务(无法立刻返回结果,需要花一定时间才能返回的任务,如I/O事件)的时候,主线程会挂起(pending)这个任务,然后在异步任务返回结果的时候再根据一定规则去执行相应的回调。浏览器是多线程的;
JS引擎和runtime的区别:引擎:解释并编译代码,让它变成能交给机器人运行的代码(runnable commands);单线程,负责维护任务队列,按照顺序把任务放入函数栈执行。runtime:就是运行环境,它提供一些对外的接口供JS调用,比如,浏览器环境、Node.js环境。不同的runtime,会提供不同的接口,比如,在 Node.js 环境中,我们可以通过require来引入模块;而在浏览器中,我们有window、 DOM。图中的异步处理模块就是runtime提供的,拥有与JS引擎互不干扰的线程。总结:JS引擎可以理解为主线程,runtime可以理解为其他的线程。
执行栈与事件队列
执行栈当调用一个方法的时候,js会生成一个与这个方法对应的执行环境(context),又叫执行上下文。这个执行环境中存在着这个方法的私有作用域,上层作用域的指向,方法的参数,这个作用域中定义的变量以及这个作用域的this对象。 而当一系列方法被依次调用的时候,因为js是单线程的,同一时间只能执行一个方法,于是这些方法被排队在一个单独的地方。这个地方被称为执行栈。
当一个脚本第一次执行的时候,js引擎会解析这段代码,并将其中的同步代码按照执行顺序加入执行栈中,然后从头开始执行。如果当前执行的是一个方法,那么js会向执行栈中添加这个方法的执行环境,然后进入这个执行环境继续执行其中的代码。当这个执行环境中的代码 执行完毕并返回结果后,js会退出这个执行环境并把这个执行环境销毁,回到上一个方法的执行环境。这个过程反复进行,直到执行栈中的代码全部执行完毕
事件队列(Task Queue)s引擎遇到一个异步事件后并不会一直等待其返回结果,而是会将这个事件挂起,继续执行执行栈中的其他任务。当一个异步事件返回结果后,js会将这个事件加入与当前执行栈不同的另一个队列,称之为事件队列。事件队列:其实是异步事件的回调组成的;
事件循环被放入事件队列不会立刻执行其回调,而是等待当前执行栈中的所有任务都执行完毕, 主线程处于闲置状态时,主线程会去查找事件队列是否有任务。如果有,那么主线程会从中取出排在第一位的事件,并把这个事件对应的回调放入执行栈中,然后执行其中的同步代码...,如此反复,这样就形成了一个无限的循环。这就是这个过程被称为“事件循环(Event Loop)”的原因

异步任务执行的优先级有区别,所以异步任务分成两类
macro task 宏任务 简称task
宏任务:script(整体代码)setInterval()setTimeout()setImmediateI/OUI render(UI交互事件)MessageChannel
micro task 微任务 简称jobs
微任务new Promise()Async/Await(实际就是promise)MutationObserver(html5新特性)process.nextTick(Node.js环境)

console.log('script start')async function async1(){await async2()console.log('async1 end')
}async function async2(){console.log('async2 end')return Promise.resolve().then(()=>{console.log('async2 end1')})
}
async1()setTimeout(function(){console.log('setTimeout')
},0);new Promise(resolve =>{console.log('Promise')resolve()
}).then(function(){console.log('promise1')
}).then(function(){console.log('promise2')
});
console.log('script end')// script start => async2 end => Promise => script end => async2 end1 => promise1 => promise2 => async1 end => setTimeout
此时执行完await并不先把await后面的代码注册到微任务队列中去,
而是执行完await之后,
直接跳出async1函数,
执行其他代码。
然后遇到promise的时候,
把promise.then注册为微任务。
其他代码执行完毕后,
需要回到async1函数去执行剩下的代码,
然后把await后面的代码注册到微任务队列当中,注意此时微任务队列中是有之前注册的微任务的。
所以这种情况会先执行async1函数之外的微任务(promise1,promise2),
然后才执行async1内注册的微任务(async1 end).
console.log('script start')async function async1(){async2()console.log('async1 end')
}async function async2(){console.log('async2 end')return Promise.resolve().then(()=>{console.log('async2 end1')})
}
async1()setTimeout(function(){console.log('setTimeout')
},0);new Promise(resolve =>{console.log('Promise')resolve()
}).then(function(){console.log('promise1')
}).then(function(){console.log('promise2')
});
console.log('script end')// script start => async2 end => Promise => script end => async2 end1 => async1 end => promise1 => promise2 => setTimeout
requestAnimationFrame属于异步执行的方法,但该方法既不属于宏任务,也不属于微任务。
window.requestAnimationFrame()
告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。
该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。requestAnimationFrame是GUI渲染之前执行,但在微服务之后,不过requestAnimationFrame不一定会在当前帧必须执行,由浏览器根据当前的策略自行决定在哪一帧执行。

步骤
script start 直接打印
async1方法调用
async1 中 await 后 async2方法调用
async2 end 打印,promise.resolve().then(()=>{console.log(async2 end1)}) 加入微任务队列
setTimeOut 宏任务,加入宏任务队列
new Promise 执行 打印 Promise; 把 .then(function(){console.log(‘promise1’)}) 加入任务队列
console.log(’script end’) 打印 script end
第一轮结束
执行第一轮第一个微任务 promise.resolve().then(()=>{ console.log(async2 end1) }),打印 async2 end1
await后等 第二轮最后执行
执行第一轮 第二个微任务 .then(function(){console.log(‘promise1’)}) 打印 promise1,添加 .then(function(){console.log(‘promise2’)}) 到微任务队列
第二轮 最后把console.log(async1 end) 加入微任务队列
第二轮结束
第三轮 执行第二轮微任务 .then(function(){console.log(‘promise2’)}) 执行,.then(function(){console.log(‘test1‘’)}) 加入微任务队列
执行 第三轮 第二个微任务 console.log(async1 end); 打印 async1 end;
第三轮结束
第四轮 执行第三轮 微任务 .then(function(){console.log(‘test1‘’)}) 打印test1
第一个宏任务结束
执行第二个宏任务 setTimeOut
打印 setTimeOut

  Promise.resolve().then(() => {console.log(0);return Promise.resolve(4);}).then((res) => {console.log(res);});Promise.resolve().then(() => {console.log(1);}).then(() => {console.log(2);}).then(() => {console.log(3);}).then(() => {console.log(5);}).then(() => {console.log(6);});


Eevnt Loop (事件循环)相关推荐

  1. 为什么JS是单线程?JS中的Event Loop(事件循环)?JS如何实现异步?setimeout?

    https://segmentfault.com/a/1190000012806637 https://www.jianshu.com/p/93d756db8c81 首先,请牢记2点: (1) JS是 ...

  2. node.js中对Event Loop事件循环的理解

    javascript是单线程的,所以任务的执行都需要排队,任务分为两种,一种是同步任务,一种是异步任务. 同步任务是进入主线程上排队执行的任务,上一个任务执行完了,下一个任务才会执行. 异步任务是不进 ...

  3. Event Loop 事件循环简介

    1.Event Loop? Event Loop 其实也是在面试中经常会出现的一个题,前端程序员回答不上来是正常的,因为 Event Loop 是 C++ 实现的,实现原理和 JavaScript 没 ...

  4. Even Loop(事件循环机制)

    1.什么是事件循环机制 Event Loop即事件循环,是解决javaScript单线程运行阻塞的一种机制. 2.为什么使用Even Loop 原因:JavaScript 是单线程的.单线程就意味着, ...

  5. Event Loop事件循环机制

    转载自:阮一峰博客<JavaScript 运行机制详解:再谈Event Loop> 一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个 ...

  6. node mysql 事件循环_NodeJs 的 Event loop 事件循环机制详解

    什么是事件轮询 事件循环是 Node.js 处理非阻塞 I/O 操作的机制--尽管 JavaScript 是单线程处理的--当有可能的时候,它们会把操作转移到系统内核中去. 下面的图表显示了事件循环的 ...

  7. JavaScript event loop事件循环 macrotask与microtask

    macrotask  姑且称为宏任务,在很多上下文也被简称为task.例如: setTimeout, setInterval, setImmediate, I/O, UI rendering. mic ...

  8. 【转载】浏览器事件循环机制(event loop)

    首先,本文转自https://juejin.im/post/5afbc62151882542af04112d 当我看完菲利普·罗伯茨的 javascript event loop的演讲的时候,就对于事 ...

  9. 技术干货 | JavaScript 之事件循环(Event Loop)

    导读:学过 JavaScript(下文简称 JS) 的都知道它是一门单线程的.非阻塞的脚本语言.单线程意味着,JS 代码在执行的任何时候,都只有一个主线程来处理所有的任务,这也就意味着 JS 无法进行 ...

最新文章

  1. BUUCTF-Reverse:reverse2
  2. Vista新特征(Features)(英文)
  3. Python第二十天 shutil 模块 zipfile tarfile 模块
  4. 阿里云mariadb无法启动问题
  5. LeetCode 820. 单词的压缩编码(后缀树)
  6. 初级程序员为避免淘汰该怎么办?
  7. 提高.NET编程水平的50个要点(转载)
  8. 女方家长和男方家长第一次见面是怎么样的?
  9. 开发环境运行正常,发布服务器后提示HTTP 错误 403.14 - Forbidden
  10. MATLAB初步进行机器学习
  11. Golang publish module
  12. 禁止网页 切屏 切换标签
  13. Excel 如何提取单元格中的多个数值
  14. Hyper 虚拟机删掉,如何恢复
  15. 给word文档加水印
  16. 阿里无人超市 “微笑打折”成世界互联网大会热点
  17. Mysql----关联查询
  18. SQL管理员sss或navicat premium连接自定义非1433端口说明
  19. 机械和计算机分数线,东北大学通信,冶金,计算机,材料,机械历年分数线
  20. 如何使用iAd在应用程序中展示Banner广告

热门文章

  1. php千封邮件怎么快速发送,如何在PHP中无限制地发送数千封电子邮件?
  2. c语言较大的整型相加,二个超长正整数的相加
  3. vue中使用高德地图 amap--基础使用方法
  4. Objective-C 日记④ 集合家族
  5. luogu P4070 [SDOI2016]生成魔咒
  6. 面向对象编程----6大设计原则
  7. Tomcat_Servlet
  8. Springboot02配制jsp
  9. Javascript实现BFS算法
  10. jenkins 备份配置信息