本文不保证能说明透彻,因为它本来就存在着混乱,但力求讲到点子上。

比较下面这几个的执行顺序setTimeout

setInterval

setImmediate (nodejs 支持,

new Promise(cb) 和 promise.then(cb)(promise 是 Promiose 的实例)

process.nextTick(nodejs)

还有一些另外的(暂时不考虑)socket.on('close', cb) close callback(nodejs)

分类

同步执行

new Promise(cb) cb 代码会同步执行,其实不属于考虑范畴了

microTask 微任务process.nextTick tickTask

promise.then(cb) microTask

microTask (在 nodejs)可以进一步划分为 tickTask 和 microTask,都是微任务队列,同类型的微任务先进先执行

优先级是 tickTask > microTask

macroTask 宏任务setTimeout

setInterval 优先级同 setTimeout,谁先被推到 timers 队列谁就先执行

setImmediate

在不同类型宏任务切换的间隙,一旦微任务队列有任务则会把微任务队列先执行完,然后继续执行下一个类型的宏任务队列。(注意是切换的时候,如果已经进入执行阶段是让该类型的宏任务执行完然后检查微任务队列,如果宏任务执行时又加入了同类型的宏任务,则会在下一个循环里面执行)

进入 timers 或者 check 或者其他的宏任务队列时,如果 microTask 任务队列中没有任务,则会在执行完优先执行的宏任务队列之后再检查 microTask 任务队列(注意:如果某个 macroTask 执行时推入了新的 microTask,它依然会先把这个类型的宏任务队列执行完,然后切换下一个类型宏任务队列时先执行微任务),如果有则执行完 microTask,然后进入下一个类型的 macroTask 队列

这里有一个非确定情况,setImmediate 和 setTimeout 的执行顺序在 nodejs 中不是固定的(nodejs 开发者这么说)。 For example, if we run the following script which is not within an I/O cycle (i.e. the main module), the order in which the two timers are executed is non-deterministic, as it is bound by the performance of the process

做个测试,下面的执行是不确定的,没有实际的意义

setTimeout(() => {

console.log('1 setTimeout')

setTimeout(() => {

console.log('2 setTimeout')

}, 0)

setImmediate(() => {

console.log('3 setImmediate')

})

}, 0)

setImmediate(() => {

console.log('4 setImmediate')

})

nodejs

可能

4 setImmediate

1 setTimeout

3 setImmediate

2 setTimeout

也可能

1 setTimeout

4 setImmediate

3 setImmediate

2 setTimeout

setTimeout 有一个隐形前提,它的第二个参数,也就是延迟执行的时间,最小是 4ms,即使指定的 0,另外注意它是 n ms 之后才可能执行,并不是 n ms 时就会执行,它的执行时间是不确定的,只能知道在 n ms 之前它不会执行。

setInterval 回调内如果是一个 while 循环,即使时间设定的 0,它也不会推无限多个回调到 timers 队列中,而是要等到这个执行完,才会把下一个回调推入 timers 队列,用 while 执行 2S 之后,清除掉 interval,发现回调只执行了一次,而不是执行很多次。

看下面的例子,这说明 setInterval 会推一个回调到 timers 队列,然后执行,然后再推下一个回调。

let count = 0

setTimeout(() => {

console.log('1 setTimeout')

}, 0)

const i = setInterval(() => {

console.log('2 setInterval')

count++

if (count === 5) {

clearInterval(i)

}

setTimeout(() => {

console.log('3 setTimeout ', count)

}, 0)

}, 0)

setTimeout(() => {

console.log('4 setTimeout')

}, 0)

---

1 setTimeout

2 setInterval

4 setTimeout

3 setTimeout 1

2 setInterval

3 setTimeout 2

2 setInterval

3 setTimeout 3

2 setInterval

3 setTimeout 4

2 setInterval

3 setTimeout 5

nodejs 事件循环

上述基本都是 macroTask 宏任务

setTimeout(() => {

console.log('1 setTimeout')

setTimeout(() => {

console.log('2 setTimeout')

}, 0)

setImmediate(() => {

console.log('3 setImmediate')

})

setTimeout(() => {

console.log('4 setTimeout')

}, 0)

setImmediate(() => {

console.log('5 setImmediate')

})

}, 0)

这个结果说明执行过程是整个队列执行完再执行下一个队列下面结果说明在同一事件循环内, check 队列会执行完之后再去执行 timers 队列。(check 未必比 timers 快)

1 setTimeout

3 setImmediate

5 setImmediate

2 setTimeout

4 setTimeout

如果在 check 队列执行期间推入 microTask 任务,那就先让当前 check 队列执行完,然后再执行 microTask,再执行 timers 队列。

setTimeout(() => {

console.log('1 setTimeout')

setTimeout(() => {

console.log('2 setTimeout')

}, 0)

setImmediate(() => {

console.log('3 setImmediate')

new Promise(res => res()).then(() => {

console.log('4 promise')

})

process.nextTick(() => {

console.log('5 nextTick')

})

})

setTimeout(() => {

console.log('6 setTimeout')

}, 0)

setImmediate(() => {

console.log('7 setImmediate')

})

}, 0)

执行结果,两个 setImmediate 被放到 check 队列,check 队列中的 setImmediate 要先全部执行完,然后再下一步,而下一步过程中 microTask 就会执行。

1 setTimeout

3 setImmediate

7 setImmediate

5 nextTick

4 promise

2 setTimeout

6 setTimeout

注意下面代码和上面代码的区别

setTimeout(() => {

console.log('1 setTimeout')

setTimeout(() => {

console.log('2 setTimeout')

}, 0)

setImmediate(() => {

console.log('3 setImmediate')

})

new Promise(res => res()).then(() => {

console.log('4 promise')

})

process.nextTick(() => {

console.log('5 nextTick')

})

setTimeout(() => {

console.log('6 setTimeout')

}, 0)

setImmediate(() => {

console.log('7 setImmediate')

})

}, 0)

---

1 setTimeout

5 nextTick

4 promise

3 setImmediate

7 setImmediate

2 setTimeout

6 setTimeout

题目

题目 1

setTimeout setInterval 是不是相同优先级?是否被推到同一个队列

setTimeout(() => {

console.log('1 timeout')

}, 0)

setInterval(() => {

console.log('2 interval')

}, 0)

setTimeout(() => {

console.log('3 timeout')

}, 0)

setInterval(() => {

console.log('4 interval')

}, 0)

setTimeout(() => {

console.log('5 timeout')

}, 0)

题目 2

setTimeout(() => {

console.log('1 setTimeout')

setTimeout(() => {

console.log('2 setTimeout')

}, 0)

setImmediate(() => {

console.log('3 setImmediate')

setImmediate(() => {

console.log('4 setImmediate')

})

process.nextTick(() => {

console.log('5 nextTick')

})

})

setImmediate(() => {

console.log('7 setImmediate')

})

setTimeout(() => {

console.log('8 setTimeout')

}, 0)

}, 0)

总结

微任务(microTask)是大爷,宏任务(macroTask)得让着微任务,但是一旦让一个类型的宏任务开始执行,那就得等这个类型的宏任务执行完,然后才能执行微任务!!!在宏任务中被推入队列的宏任务得在下一轮才能开始执行,这一轮没新宏任务的份。

欢迎大家关注我的掘金和公众号,算法、TypeScript、React 及其生态源码定期讲解。

hook 循环点击事件用哪个_JS 事件循环 event loop,看完你可以答对 90% 的事件循环题...相关推荐

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

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

  2. JavaScript基础:浅聊事件循环(Event LooP)以及微任务,宏任务,DOM渲染

    一直说JavaScript是单线程的执行的(当然也可以通过其它其它的方式异步,本篇暂时不聊). 内核的组成 首先聊一下浏览器的内核组成部分,当然下面也不是全部,而只是说一些常见的. 主线线程 js引擎 ...

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

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

  4. JAVA script 循环 图片_深入分析JavaScript 事件循环(Event Loop)

    事件循环(Event Loop),是每个JS开发者都会接触到的概念,但是刚接触时可能会存在各种疑惑. 众所周知,JS是单线程的,即同一时间只能运行一个任务.一般情况下这不会引发问题,但是如果我们有一个 ...

  5. 事件轮询(Event Loop) 宏任务与微任务

    事件轮询(Event Loop) 宏任务与微任务 文章目录 事件轮询(Event Loop) 宏任务与微任务 前言 Javascript诞生 Javascript如何执行 Event Loop是什么? ...

  6. 【Android 插件化】Hook 插件化框架 ( Hook 实现思路 | Hook 按钮点击事件 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  7. js 循环 等待异步执行完再执行_JS异步执行机制——事件循环(Event Loop)

    JS异步执行机制--事件循环(Event Loop) 本文首发地址: 前端基础 | JS异步执行机制--事件循环(Event Loop)​www.brandhuang.com 先祭出一段代码,你清楚它 ...

  8. js 异步执行_JS异步执行机制——事件循环(Event Loop)

    JS异步执行机制--事件循环(Event Loop) 本文首发地址: 前端基础 | JS异步执行机制--事件循环(Event Loop)​www.brandhuang.com 先祭出一段代码,你清楚它 ...

  9. JavaScipt 中的事件循环(event loop),以及微任务 和宏任务的概念

    说事件循环(event loop)之前先要搞清楚几个问题. 1. js为什么是单线程的? 试想一下,如果js不是单线程的,同时有两个方法作用dom,一个删除,一个修改,那么这时候浏览器该听谁的? 2. ...

最新文章

  1. 将一张100元的钞票换成1元、5元和10元的钞票,每种钞票至少一张,编写程序输出所有的换法,循环次数需要尽可能地少。
  2. SpringMVC入门案例
  3. python中str和repr_python中str()和repr()函数的区别
  4. 太强了!这个 Jupyter notebook 离线工具可以用一辈子!
  5. synchronized的理解
  6. STM32中断优先级的管理(NVIC)
  7. HP服务器F10 Function Disabled,无法使用F10安装操作系统
  8. 《C和C++游戏趣味编程》 第8章 十步万度
  9. 修改jupyter notebook的默认工作目录
  10. 矩阵相关的一些中英文对照术语
  11. loj10157. 「一本通 5.2 例 5」皇宫看守
  12. 一文了解Android游戏SDK开发
  13. java网上销售外文文献_基于java网上购物论文英文的参考文献欣赏
  14. 3DMAx Panda Directx Exporter 导出 X插件
  15. 阿里云服务器ECS-Apollo搭建MQTT服务器(Windows环境)
  16. 对比了百度统计和CNZZ后,我最终选择了51LA
  17. JPA 关联表添加关联条件@Where、@WhereJoinTable()
  18. 美国北亚利桑那大学计算机专业排名,北亚利桑那大学排名 综合排名和专业排名介绍...
  19. 蓝桥杯 2014-4 大衍数列
  20. 转 史上最详细的Hadoop环境搭建

热门文章

  1. android布局的属性,android
  2. c++ 内存管理_Python Bindings - 从 Python 调用 C/C++
  3. 向大学生教授物理的更好方法
  4. 当年赫赫有名的“四大工学院”,如今都发展得怎样?依然牛气冲天
  5. AI算法连载14:统计之模型选择
  6. 《暗时间》-----摘记
  7. 全球首款乘云而来的存储产品CDS诞生!
  8. 深入浅出FlatBuffers原理
  9. 深度强化学习在时序数据压缩中的应用--ICDE 2020收录论文
  10. Dragonfly成为CNCF孵化项目,我们与基金会首位华人TOC聊了聊