事件循环

Posted lijianming180

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了事件循环相关的知识,希望对你有一定的参考价值。

本文记录对事件循环的理解

setTimeout与setInterval

  • 定时器不是javascript自身的一个功能,是javascript运行在浏览器环境中浏览器为其实现的一个功能。
  • javascript是单线程的,同一时间只能执行一个代码块,这些代码块阻塞了异步事件的执行。当一个异步事件发生时(鼠标点击,定时器,ajax等),它就会排队,等线程空闲时才能执行。
  • 异步队列中的处理程序会有优先级,鼠标点击处理程序优先级会高于Timer处理程序与Interval处理程序。
    举例:
    一个javascript程序包括主程序代码,setTimeout,setInterval时,执行到setInterval时,会进入到队列中排队处理程序。队列中的setInterval处理程序在设定的时间内要执行但此时主程序代码块还没执行结束,则此次处理程序不能被执行。在下一次setInterval处理程序要执行时主程序还是没有执行结束,因为队列中已有setInterval处理程序,则不在向队列中推入setInterval处理程序,即此次作废。而setTimeout处理程序、鼠标点击处理程序则在异步队列中等主程序执行结束之后执行(setTnterval处理事件也是)。队列中事件处理程序的先后顺序由浏览器算法决定。

不同点:

1
2
3
4
5
6
7
setTimeout(function() {
setTimeout(repeatMe, 10);
}, 10);

setInterval(function() {

}, 10)

setTimeout要在前一个callback回调执行结束并延迟10ms以后,才能再次执行setTimeout(),
而setInterval()则是每隔10ms就尝试执行callback回调,而不关注上一个callback是何时执行的。

任务队列macrotask与microtask

事件循环中的任务队列主要包括macrotask与microtask,执行的顺序为:

  1. 在 macrotask 队列中执行最早的那个 task ,然后移出
  2. 执行 microtask 队列中所有可用的任务,然后移出
  3. 下一个循环,执行下一个 macrotask 中的任务 (再跳到第2步)

macrotask主要有setInterval与setTimeout,miscrotask主要有Promise.then()的回调。mascrotask产生的microtask可以在本次循环执行,而macrotask则需要下次循环执行。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
大专栏  事件循环lass="line">27
28
29
30
31
32
33
34
35
36
37
38
39
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')
})

以上代码的输出结果?
首次执行setTimeout、setTimeout,作为一个macrotask,将其回调函数放入自己的队列之中。在下一次循环中执行回调
其次会执行microtask。
重复以上步骤,输出:
promise 1
promise 2
setInterval
setTimeout 1
promise 3
promise 4
setInterval
setTimeout 2
promise 5
promise 6

以上是关于事件循环的主要内容,如果未能解决你的问题,请参考以下文章

常用python日期日志获取内容循环的代码片段

使用从循环内的代码片段中提取的函数避免代码冗余/计算开销

Android 事件分发事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )(代码片段

AVKit – 视频片段仅循环 2 次

c_cpp 这个简单的代码片段显示了如何使用有符号整数在C中完成插值。 for()循环确定要插入的范围

C# 中 XBOX 控制器的事件处理程序?