事件轮询机制
任务队列分为
-
宏任务队列
-
微任务队列
当碰上异步代码时,会将异步代码传给web API 由web API 将异步代码放到任务队列中,script整体代码、setTimeout、setTnterval、I/O…放在宏任务队列中, promise.then()放在微任务队列中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZTecKceA-1646959896185)(C:\Users\Rick.li\AppData\Local\Temp\1646924656823.png)]
对上述代码分析:
1.先将整体代码块放进调用栈,从上到下执行
setTimeout和.then后面的代码为异步代码段
将其按照顺序放进宏任务队列和微任务队列
这个阶段输出 1 3 5
2.调用栈每空一次,清空一次微任务队列
所以接下来是将微任务队列中的代码段依次放进调用栈
这个阶段得到结果是 1 3 5 4
3.微任务队列清空,访问宏任务队列,将宏任务队列中第一个代码段放进调用栈中执行
这个阶段得到的结果是 1 3 5 4 2
4.调用栈为空,再次访问微任务队列,微任务列表为空,转访问宏任务列表第一个代码段,宏任务列表也为空,则执行结束
进一步详解:
JavaScript
语言是单线程的,同一个时间只能做一件事;- 遵循事件循环机制,当JS解析执行时,会被引擎分为两类任务,同步任务(
synchronous
) 和异步任务(asynchronous
)。对于同步任务来说,会被推到执行栈按顺序去执行这些任务。对于异步任务来说,当其可以被执行时,会被放到一个任务队列(task queue
)里等待JS引擎去执行。当执行栈中的所有同步任务完成后,JS
引擎才会去任务队列里查看是否有任务存在,并将任务放到执行栈中去执行,执行完了又会去任务队列里查看是否有已经可以执行的任务。这种循环检查的机制,就叫做事件循环(Event Loop
)。对于任务队列,其实是有更细的分类。其被分为 微任务(microtask
)队列 & 宏任务(macrotask
)队列。
参考:https://blog.csdn.net/WuLex/article/details/106058625
关于promise的怪异机制
promise一般用于异步代码段
先看一段代码:
最开始我的结果是 1 11 2 21 23 12
按照正常的事件轮询机制,这就是从上到下,依次输出,因为.then后面的代码段必须得等到前面的代码段执行完才能执行,但是这段代码段把小编我给整迷糊了
真正的输出结果并非如此,而是这样的
为什么是这样呢?
发现没四次向前返一次
这段代码的另一个版本:
输出结果又让我诧异了:
竟然没有改变输出顺序
因为多了一个return
为什么????????