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

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

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

我们知道 DOM 操作会触发浏览器对文档进行渲染,如修改排版规则,修改背景颜色等等,那么这类操作是如何在浏览器当中奏效的?至此我们已经知道了事件循环是如何执行的,事件循环器会不停的检查事件队列,如果不为空,则取出队首压入执行栈执行。当一个任务执行完毕之后,事件循环器又会继续不停的检查事件队列,不过在这间,浏览器会对页面进行渲染。这就保证了用户在浏览页面的时候不会出现页面阻塞的情况,这也使 JS 动画成为可能, jQuery 动画在底层均是使用 setTimeout 和 setInterval 来进行实现。想象一下如果我们同步的执行动画,那么我们不会看见任何渐变的效果,浏览器会在任务执行结束之后渲染窗口。反之我们使用异步的方法,浏览器会在每一个任务执行结束之后渲染窗口,这样我们就能看见动画的渐变效果了。

Several runtimes communicating together

A web worker or a cross-origin iframe has its own stack, heap, and message queue. Two distinct runtimes can only communicate through sending messages via the postMessagemethod. This method adds a message to the other runtime if the latter listens to messageevents.

--------------------------------------------------------------------分割线--------------------------------------------------------------------------------

放个面试题,抛个砖:

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,如此往复循环至结束

javascript event loop的更多相关文章

  1. JavaScript Event Loop和微任务、宏任务

    为什么JavaScript是单线程? JavaScript的一大特点就是单线程, 同一时间只能做一件事情,主要和它的用途有关, JavaScript主要是控制和用户的交互以及操作DOM.注定它是单线程 ...

  2. javaScript Event Loop + NodeJs问题解析

    http://www.ruanyifeng.com/blog/2014/10/event-loop.html https://github.com/ElemeFE/node-interview/tre ...

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

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

  4. 深入理解 JavaScript 事件循环(一)— event loop

    引言 相信所有学过 JavaScript 都知道它是一门单线程的语言,这也就意味着 JS 无法进行多线程编程,但是 JS 当中却有着无处不在的异步概念 .在初期许多人会把异步理解成类似多线程的编程模式 ...

  5. JavaScript事件循环(Event Loop)机制

    JavaScript 是单线程单并发语言 什么是单线程 主程序只有一个线程,即同一时间片断内其只能执行单个任务. 为什么选择单线程? JavaScript的主要用途是与用户互动,以及操作DOM.这决定 ...

  6. JavaScript 事件循环 — event loop

    引言 相信所有学过 JavaScript 都知道它是一门单线程的语言,这也就意味着 JS 无法进行多线程编程,但是 JS 当中却有着无处不在的异步概念 .在初期许多人会把异步理解成类似多线程的编程模式 ...

  7. event loop 与 vue

    结论 对于event loop 可以抽象成一段简单的代码表示 for (macroTask of macroTaskQueue) { // 1. Handle current MACRO-TASK h ...

  8. javascript运行模式:并发模型 与Event Loop

    看了阮一峰老师的JavaScript 运行机制详解:再谈Event Loop和[朴灵评注]的文章,查阅网上相关资料,把自己对javascript运行模式和EVENT loop的理解整理下,不一定对,日 ...

  9. JavaScript 运行机制详解:再谈Event Loop

    原文地址:http://www.ruanyifeng.com/blog/2014/10/event-loop.html 一年前,我写了一篇<什么是 Event Loop?>,谈了我对Eve ...

随机推荐

  1. [TJOI2007] 线段 (动态规划)

    题目链接 Solution 传统的线性 \(dp\) . \(f[i][0]\),\(f[i][1]\) 分别表示最后一次在 \(i\) ,然后在 左边或者右边的最小步数. 然后就每次根据上一次左边和 ...

  2. CENTOS6.5 安装 mysql5.6 以及搭建双主

    一.Mysql5.6.10安装 1.1.必要软件 yum -y install gcc gcc-c++ autoconf automake bison ncurses-devel libtool-lt ...

  3. 转:Android Context的理解

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40481055,本文出自:[张鸿洋的博客] 本文大多数内容翻译自:http://w ...

  4. 全自动google检索后台

    是不是每天为了找后台,伤破了蛋,每次在google输入”site:www.xxx.com intitle:登陆”.是不是手都累麻了,无聊又浪费时间.有了它,你的蛋就不用在碎了 直接上源码 1 2 3 ...

  5. Log4Net日志分类和自动维护

    背景 在程序中,我们调试运行时信息,Log4Net是一个不错的解决方案.不知道是我用的不好,用到最后反而都不想看日志了.原因是因为我n个功能使用的默认的Logger来记录日志,这样以来,所有功能记录的 ...

  6. MFC的使用——在共享DLL中使用MFC、在静态库中使用MFC(转)

    原文转自 https://blog.csdn.net/albertsh/article/details/52838419 1.使用标准Windows库 使用WINDOWS SDK API库,不使用MF ...

  7. fatal error LNK1104: 无法打开文件“LIBC.lib”错误(转)

    原文转自 http://blog.csdn.net/qq1028850792/article/details/41546043 方法一: 用VS2005重新编译某个工程的发生了链接错误,现在把这个解决 ...

  8. jQuery的动画方法

    /* animate参数: 参数一:要改变的样式属性值,写成字典的形式 参数二:动画持续的时间,单位为毫秒,一般不写单位 参数三:动画曲线,默认为‘swing’,缓冲运动,还可以设置为‘linear’ ...

  9. ActiveMQ StartUp

    从http://activemq.apache.org/activemq-5132-release.html 下载 解压 从apache-activemq-5.13.2\bin\win64\wrapp ...

  10. 华农oj 2192: hzk又在打人【CRT合并/待补】

    2192: hzk又在打人 Time Limit: 12 Sec Memory Limit: 512 MB Submit: 52 Solved: 1 [Submit][Status][Web Boar ...