js中一个好玩的api之queueMicrotask
介绍
今天闲来无聊,偶然看到个api – queueMicrotask,其MDN地址为queueMicrotask,觉得挺有意思的,于是想写一篇文章来跟大家分享一下。
用法
首先,这个api看字面意思就知道和微任务有关,至于js中的宏任务和微任务,我就不多说了,默认大家都知道这些东西,不了解的读者可以去查阅相关的资料。
1 | queueMicrotask(function() {/* ... */}) |
可以看到,此api需要传入一个回调函数作为参数,然后以微任务的形式执行此回调函数,换言之,就是把此回调函数放入此次js事件循环的微任务队列中。
我们不妨来看几个例子:
例子1:
1 | console.log(111) |
那么,此例子中的代码执行结果是什么呢?
1 | 111 |
你猜对了吗?
兼容性
queueMicrotask的polyfill
如果当前环境不支持queueMicrotask,则可以像下面这样模拟:
1.MDN
1 | if (typeof queueMicrotask !== "function") { |
2.core-js
相比较 MDN 的实现,core-js 会复杂一些,它同时考虑了 nodejs 和 browser 两种情况,同时利用链表数据结构来模拟微任务队列的执行单元,同时实现了一个 flush 方法表示执行全部的微任务单元。
还实现了一个 notify 方法,该方法会根据具体的 js 运行时环境以及 api 的支持情况,分别尝试使用 process.nextTick、MutationObserver 和 Promise.resolve 以及最基本的宏任务 api 来执行 flush方法,变相模拟微任务的执行过程。
为什么我们需要这个 api?
从微任务本身的概念来说的话,就是当我们期望某段代码,不阻塞当前执行的同步代码,同时又期望它尽可能快地执行时,我们就需要它。由于它是一个用于指派微任务的底层 api,我们很可能会在其中无限制地指派微任务到其队列之中,这样做的效果就是,浏览器的微任务队列始终处于非空状态,这将导致控制权始终无法交还给浏览器进行下一次事件循环,需要注意的是,不要长时间连续使用此api(比如递归),否则js的执行将一直在做添加微任务和清空微任务队列的工作,最终导致浏览器卡死,比如下面这样:
1 | function infiniteFn() { |