小工具知识网

当前位置: 首页 > 行业知识 > 向微队列添加任务的四种方式

行业知识

向微队列添加任务的四种方式

2026-11-03 18:55:43 来源:互联网转载

向微队列添加任务的四种方式

关于���任务,微队列,事件循环,可参考:深入:微任务与 Javascript 运行时环境 - Web API 接口参考 | MDN (mozilla.org)

先说答案, 四种方法:

  1. Promise.resolve().then();
  2. MutationObserver
  3. process.nextTick();
  4. queueMicrotask()

Promise.resolve().then()

查看ECMA-262关于then方法的描述:

可知then方法会在promise状态为fulfilled或rejected时将对应的任务(onFulfilled和onRejected)放到任务队列中,然后注意到MDN在一篇关于微任务的文章中提到:

JavaScript 中的 promise 和 Mutation Observer API 都使用微任务队列去运行它们的回调函数

于是我们可以知道then方法的回调将会被添加到微队列中执行, 若查看V8引擎源码可进一步佐证这一点。

这样一来,我们就可以用以下代码向微队列中添加一个任务:

const task = () => {    console.log("do somthing");}Promise.resolve().then(task);

进一步, 根据ECMA-262的描述(上图红框部分), 当promise状态为rejected时,onRejected也会被添加到微队列, 于是以下代码也可以达到相同的效果:

//以下两种方法等价Promise.reject().then(null, task);Promise.reject().catch(task);

验证一下, 执行以下代码, 发现打印顺序符合预期:

setTimeout(() => {  console.log("timeout");}, 0);Promise.resolve().then(() => {  console.log("promise resolve");})Promise.reject().then(null, () => {  console.log("promise reject");});Promise.reject().catch(() => {  console.log("promise catch");});console.log("同步");//打印结果:// 同步// promise resolve// promise reject// promise catch// timeout

MutationObserver API

同样根据上文提到的MDN的描述, 使用MutationObserver也可以达到向微队列中添加任务的目的, 结合MutationObserver的用法可以封装一个通用的函数:

    function enqueueMicroTaskByMutationObserver(task) {      if (typeof task != "function") {        throw "task必须为函数";      }      let m = new MutationObserver(task);      let p = document.createElement("p");      m.observe(p, {        childList: true      });      p.innerText = "1";    }

注意: nodejs环境不支持MutationObserver API, 因此这个方法只能在浏览器环境中使用

在html中运行以下代码验证, 打印顺序符合预期:

      Document      function enqueueMicroTaskByMutationObserver(task) {      if (typeof task != "function") {        throw "task必须为函数";      }      let m = new MutationObserver(task);      let p = document.createElement("p");      m.observe(p, {        childList: true      });      p.innerText = "1";    }    setTimeout(() => {      console.log("time out");    }, 0);    enqueueMicroTaskByMutationObserver(() => {      console.log("MutationObserver");    })  

process.nextTick()

与MutationObserver API相反,这个方法只能用于Node环境,根据Node文档的描述:

process.nextTick() 将 callback 添加到 “下一个滴答队列”。在 JavaScript 堆栈上的当前操作运行完成之后,且在允许事件循环继续之前,此队列将被完全排空。

暂时可将"滴答队列"简单理解为微队列,实际上,"滴答队列"的优先级似乎比微队列更高, 观察以下代码:

setTimeout(() => {  console.log("timeout");}, 0);Promise.resolve().then(() => {  console.log("promise resolve");})process.nextTick(() => {  console.log("tick");})console.log("同步");

发现无论执行多少次, "tick"总是先于"promise resolve"打印,于是推测"滴答队列"的优先级似乎比微队列更高.

queueMicrotask

在不考虑兼容性的情况下, 应当首选这个方法, 因为这个方法就是专门用来做将微任务加入队列这件事的, 参考MDN:queueMicrotask() - Web API 接口参考 | MDN (mozilla.org)

同时, queueMicrotask在浏览器和node环境中都可以使用且用起来也是最简单的, 用法如下:

queueMicrotask(() => {  console.log("do somthing");})

如有错漏,恳请指出

上一篇:轻松下载指南手把手教你下载yundowm,操作无忧!

下一篇:mac下VSCode配置 SSH连接远程服务器+免密连接