转: 原文 http://blog.csdn.net/sjn0503/article/details/76087631

----------------------------------------------------

放个面试题,抛个砖:

console.log('start')

const interval = setInterval(() => {
console.log('setInterval')
}, 0) setTimeout(() => {
console.log('setTimeout 1')
Promise.resolve()
.then(() => {
console.log('promise 3')
})
.then(() => {
console.log('promise 4')
})
.then(() => {
setTimeout(() => {
console.log('setTimeout 2')
Promise.resolve()
.then(() => {
console.log('promise 5')
})
.then(() => {
console.log('promise 6')
})
.then(() => {
clearInterval(interval)
})
}, 0)
})
}, 0) Promise.resolve()
.then(() => {
console.log('promise 1')
})
.then(() => {
console.log('promise 2')
})

不着急揭晓答案,先分析

首先知晓:

js是单线程语言

也就是说一次就只能做一件事情。

多数的网站不需要大量计算,程序花费的时间主要集中在磁盘 I/O 和网络 I/O 上面

虽然SSD读取很快,但和CPU处理指令的速度比起来也不在一个数量级上,而且网络上一个数据包来回的时间更慢(注意过游戏的延迟吗)

so: 一些cpu直接执行的任务就成了优先执行主线任务,然后需要io返回数据的任务就成了等待被执行的任务

所以才会有同步任务(synchronous)和异步任务(asynchronous)之分

同步任务:

在主线程上排队执行的任务,前一个任务执行完毕,才能执行后一个任务;

异步任务:

不进入主线程、而进入”任务队列”(task queue)的任务,只有”任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

总之:

只要主线程空了,就会去读取”任务队列”,这就是JavaScript的运行机制

Microtasks Macrotasks

任务队列不止一个,还有 microtasks 和 macrotasks

microtasks:

  • process.nextTick
  • promise
  • Object.observe
  • MutationObserver

macrotasks:

  • setTimeout
  • setInterval
  • setImmediate
  • I/O
  • UI渲染

whatwg规范:https://html.spec.whatwg.org/multipage/webappapis.html#task-queue

  • 一个事件循环(event loop)会有一个或多个任务队列(task queue)
  • task queue 就是 macrotask queue
  • 每一个 event loop 都有一个 microtask queue
  • task queue == macrotask queue != microtask queue
  • 一个任务 task 可以放入 macrotask queue 也可以放入 microtask queue 中

理解了这些定义之后,再看执行原理:

事件循环的顺序,决定了JavaScript代码的执行顺序。它从script(整体代码)开始第一次循环。之后全局上下文进入函数调用栈。直到调用栈清空(只剩全局),然后执行所有的micro-task。当所有可执行的micro-task执行完毕之后。循环再次从macro-task开始,找到其中一个任务队列执行完毕,然后再执行所有的micro-task,这样一直循环下去。

还要注意一点:

包裹在一个 script 标签中的js代码也是一个 task 确切说是 macrotask。

所以文首面试题的答案为:

start 
promise 1 
promise 2 
setInterval 
setTimeout 1 
promise 3 
promise 4 
setInterval 
setTimeout 2 
promise 5 
promise 6

简单来讲,整体的js代码这个macrotask先执行,同步代码执行完后有microtask执行microtask,没有microtask执行下一个macrotask,如此往复循环至结束.

--------------------------------------------------------2017年11月14日21:35:17---------------------------------------------------------------

另外,这篇文章也不错

这个知识点。。。

https://blog.keifergu.me/2017/03/23/difference-between-javascript-macrotask-and-microtask/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io

前端基础进阶系列

这个系统也超屌!!

http://www.jianshu.com/p/cd3fee40ef59

=======================

Macrotask 和 microtask 都是属于上述的异步任务中的一种,我们先看一下他们分别是哪些 API :

  • macrotaskssetTimeoutsetIntervalsetImmediate, I/O, UI rendering
  • microtasksprocess.nextTickPromisesObject.observe(废弃), MutationObserver

任务队列分为 macrotasks 和 microtasks,而Promise中的then方法的函数会被推入 microtasks 队列,而setTimeout的任务会被推入 macrotasks 队列。在每一次事件循环中,macrotask 只会提取一个执行,而 microtask 会一直提取,直到 microtasks 队列清空

注:一般情况下,macrotask queues 我们会直接称为 task queues,只有 microtask queues 才会特别指明。

那么也就是说如果我的某个 microtask 任务又推入了一个任务进入 microtasks 队列,那么在主线程完成该任务之后,仍然会继续运行 microtasks 任务直到任务队列耗尽。

而事件循环每次只会入栈一个 macrotask ,主线程执行完该任务后又会先检查 microtasks 队列并完成里面的所有任务后再执行 macrotask。

=======================

测试代码:

<script>
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
},0); Promise.resolve().then(function() {
console.log('promise');
}).then(function() {
console.log('promise2');
}); console.log('script end'); </script>

event loop js事件循环 microtask macrotask的更多相关文章

  1. Event Loop js 事件循环初理解

    浏览器环境 执行栈 所有的 JS 代码在运行是都是在执行上下文中进行的.执行上下文是一个抽象的概念,JS 中有三种执行上下文: 全局执行上下文,默认的,在浏览器中是 window 对象 函数执行上下文 ...

  2. 详解JavaScript中的Event Loop(事件循环)机制

    前言 我们都知道,javascript从诞生之日起就是一门单线程的非阻塞的脚本语言.这是由其最初的用途来决定的:与浏览器交互. 单线程意味着,javascript代码在执行的任何时候,都只有一个主线程 ...

  3. JavaScript 运行机制以及Event Loop(事件循环)

    一.JavaScript单线程 众所周知JavaScript是一门单线程语言,也就是说,在同一时间内JS只能做一件事.为什么JavaScript不能有多个线程呢?这样不是能够提高效率吗? JavaSc ...

  4. js事件循环机制(Event Loop)

    javascript从诞生之日起就是一门  单线程的  非阻塞的  脚本语言,单线程意味着,javascript代码在执行的任何时候,都只有一个主线程来处理所有的任务,非阻塞靠的就是 event lo ...

  5. 理解js事件循环(event loop)

    队列:先进先出 栈:后进先出 javascript的Event Loop 和 Node.js的Event Loop 区别: js(运行在浏览器),有主线程.异步任务队列的概念: node.js使用li ...

  6. js 事件循环机制 EventLoop

    js 的非阻塞I/O  就是由事件循环机制实现的 众所周知  js是单线程的 也就是上一个任务完成后才能开始新的任务 那js碰到ajxa和定时器.promise这些异步任务怎么办那?这时候就出现了事件 ...

  7. Node.js 事件循环(Event Loop)介绍

    Node.js 事件循环(Event Loop)介绍 JavaScript是一种单线程运行但又绝不会阻塞的语言,其实现非阻塞的关键是“事件循环”和“回调机制”.Node.js在JavaScript的基 ...

  8. js事件循环

    之前有看过一些事件循环的博客,不过一阵子没看就发现自己忘光了,所以决定来自己写一个博客总结下! 首先,我们来解释下事件循环是个什么东西: 就我们所知,浏览器的js是单线程的,也就是说,在同一时刻,最多 ...

  9. JS 事件循环机制 - 任务队列、web API、JS主线程的相互协同

    一.JS单线程.异步.同步概念 从上一篇说明vue nextTick的文章中,多次出现“事件循环”这个名词,简单说明了事件循环的步骤,以便理解nextTick的运行时机,这篇文章将更为详细的分析下事件 ...

随机推荐

  1. Spartan6系列之Spartan6系列之芯片时钟资源深入详解

    1.   时钟资源概述 时钟设施提供了一系列的低电容.低抖动的互联线,这些互联线非常适合于传输高频信号.最大量减小时钟抖动.这些连线资源可以和DCM.PLL等实现连接. 每一种Spartan-6芯片提 ...

  2. CNN结构:可用于时序预测复合的DNN结构-AcGANs、误差编码网络 ENN

    前言:模式识别问题 模式函数是一个从问题定义域到模式值域的一个单射. 从简单的贝叶斯方法,到只能支持二分类的原始支持向量机,到十几个类的分类上最好用的随机森林方法,到可以支持ImageNet上海量18 ...

  3. MySql学习笔记(三) —— 聚集函数的使用

    1.AVG() 求平均数 select avg(prod_price) as avg_price from products; --返回商品价格的平均值 ; --返回生产商id为1003的商品价格平均 ...

  4. Redis系列(十)--集群cluster

    在之前学习了Master-Slave.Sentinel模式,但是在某些情况下还是无法满足系统对QPS等要求,这时候就需要Cluster,Redis3.0支持了cluster 一.为什么使用Cluste ...

  5. c# Dictionary 扩展方法

    主要用于接口请求,数据转换 #region Dictionary 扩展方法 public static string getString(this Dictionary<string, stri ...

  6. 数据结构与算法(3)- C++ STL与java se中的vector

    声明:虽然本系列博客与具体的编程语言无关.但是本文作者对c++相对比较熟悉,其次是java,所以难免会有视角上的偏差.举例也大多是和这两门语言相关. 上一篇博客概念性的介绍了vector,我们有了大致 ...

  7. springmvc视图解析

    SpringMVC 视图解析的几种方式: 在视图解析的过程中,需要知道逻辑view的名字,model的名字以访问model和view. 使用jsp进行解析,InternalResourceViewRe ...

  8. [Algorithm] 7. Serialize and Deserialize Binary Tree

    Description Design an algorithm and write code to serialize and deserialize a binary tree. Writing t ...

  9. Python学习笔记(2)数值类型

    进制转换 int函数任意进制转换为10进制 第一个参数传入一个字符串,任意进制的,第二个参数传入对这个字符串的解释,解释他为几进制 hex oct bin转换进制为16 8 或者2进制 例题中石油87 ...

  10. sql常用的命令

    SELECT NAME, database_id,create_date 创建时间,is_auto_shrink_on 自动收缩,state_desc 状态,recovery_model_desc 恢 ...