转: 原文 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. 378 Kth Smallest Element in a Sorted Matrix 有序矩阵中第K小的元素

    给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素.请注意,它是排序后的第k小元素,而不是第k个元素.示例:matrix = [   [ 1,  5,  9],   [ ...

  2. EditPlus里面自带有更改文件编码的功能

  3. ASP MVC

    V-view 显示层 C-controller 控制层 M-model 模型 D-database 数据库 S-Service 服务 D-Database/Dao 数据库/访问数据库的方法 View即 ...

  4. The Runtime Interaction Model for Views-UI布局事件处理流程

    The Runtime Interaction Model for Views Any time a user interacts with your user interface, or any t ...

  5. 梦想MxWeb3D,三维CAD协同设计平台 2019.04.09更新

    SDK开发包下载地址: http://www.mxdraw.com/ndetail_10140.html 在线演示网址: http://www.mxdraw.com:3000/ 1.  增加上传dwg ...

  6. JavaScipt30(第八个案例)(主要知识点:canvas)

    承接上文,这是第8个案例,要实现的效果是按住鼠标不放,进行拖动时可以在画布上画出不同粗细不同颜色的曲线. 附上项目链接: https://github.com/wesbos/JavaScript30 ...

  7. 01C++编辑编译运行环境

    C++编辑编译运行环境 Bloodshed Dev-C++ Microsoft Visual Studio

  8. luogu P3899 [湖南集训]谈笑风生 线段树合并

    Code: #include<bits/stdc++.h> #define maxn 300002 #define ll long long using namespace std; vo ...

  9. Leetcode747至少是其他数字两倍的最大数

    Leetcode747至少是其他数字两倍的最大数 在一个给定的数组nums中,总是存在一个最大元素 .查找数组中的最大元素是否至少是数组中每个其他数字的两倍.如果是,则返回最大元素的索引,否则返回-1 ...

  10. buf.readInt32BE()

    buf.readInt32BE(offset[, noAssert]) buf.readInt32LE(offset[, noAssert]) offset {Number} 0 <= offs ...