任务执行的时空舞台:宏任务、微任务与DOM变化监听的完美协奏曲

随着浏览器应用的不断发展,我们在处理任务的方式上也经历了一些变革。传统的消息队列机制在某些领域已经不能满足实时性和效率的需求,因此出现了微任务的概念,使我们能够更灵活地在实时性和效率之间取得平衡。

1.宏任务

在浏览器中,大部分任务都是在主线程上执行的,这包括了渲染事件、用户交互事件、JavaScript 脚本执行事件、网络请求完成、文件读写完成等。为了协调这些任务的执行,浏览器引入了消息队列和事件循环机制。渲染进程内部维护多个消息队列,如延迟队列、普通消息队列等。主线程通过一个 for 循环不断从这些任务队列中取出任务并执行。

消息队列中的任务被称为宏任务,其执行过程大致分为以下步骤:

  1. 先从消息队列中取出一个最老的任务,称为`oldestTask。
  2. 然后循环系统记录任务开始执行的时间,并把这个oldestTask设置为当前正在执行的任务。
  3. 当任务执行完成之后,删除当前正在执行的任务,并从对应的消息队列中删掉这个oldestTask
  4. 最后统计执行完成的时长等信息。

尽管宏任务是一种可靠的执行方式,但对于对时间精度有更高要求的场景,宏任务的粗时间颗粒度就显得不够灵活。

2.微任务

为了解决宏任务的时间颗粒度问题,引入了微任务的概念。微任务是一种需要异步执行的函数,其执行时机是在主函数执行结束之后、当前宏任务结束之前。 每个宏任务都会关联一个微任务队列 ,而在 JavaScript 执行脚本时,V8 引擎会在全局执行上下文中创建一个微任务队列。

微任务产生的时机和执行微任务的时机

微任务产生的时机

  1. 使用MutationObserver监控某个DOM节点,然后通过JavaScript来修改这个节点,或者为这个节点添加、删除子节点,当DOM节点发生变化时,就会产生DOM变化记录的微任务。
  2. 使用promise,当调用Promise.resolve()或者Promise.reject()的时候也会产生微任务。

执行微任务的时机

微任务的执行时机通常在当前宏任务中的 JavaScript 快执行完成时,这个时刻被称为微任务检查点 。在检查点时,JavaScript 引擎会检查全局执行上下文中的微任务队列,并按照顺序执行队列中的微任务。值得注意的是,如果在执行微任务的过程中产生了新的微任务,它将被添加到微任务队列中,并在当前宏任务中继续执行,而不会推迟到下个宏任务。

3.监听DOM变化方法的演变

Web开发中,监听DOM变化的方法经历了一些演变。以下是一些常用的监听 DOM 变化的方法及其演变:

1. 轮询(Polling):

早期的 DOM 监听方式是通过轮询检查 DOM 是否发生变化。通过定期检查 DOM 结构的变化,然后执行相应的操作。这种方法的缺点是效率低下,不够实时,同时可能会造成性能问题。

js 复制代码
setInterval(function () {
    // 检查 DOM 变化
    // 执行相应操作
}, 1000);  // 每秒轮询一次

2. 事件监听器:

随着浏览器的发展,引入了更为实时的事件监听器,允许开发者监听 DOM 元素的特定事件,从而实时获取变化。

js 复制代码
document.addEventListener('change', function (event) {
    // 处理 DOM 变化事件
});

3. MutationObserver:

MutationObserver 是一个现代的、高效的 API,用于异步监听DOM的变化。它能够捕获到DOM 树的变化,包括节点的增加、删除、属性的变化等。相对于事件监听器,MutationObserver 提供了更为灵活和强大的功能。

js 复制代码
// 创建一个 MutationObserver 实例
const observer = new MutationObserver(function (mutationsList, observer) {
    // 处理 DOM 变化
});

// 配置监听选项
const config = { attributes: true, childList: true, subtree: true };

// 开始监听
observer.observe(document.body, config);

MutationObserver 的优势在于它不会阻塞主线程,而是通过异步方式捕获 DOM 变化,因此更适用于大规模的、频繁的 DOM 操作。

4.性能优化建议

微任务的合理使用

在使用微任务时,需要谨慎并避免过度依赖微任务来处理任务。过多的微任务可能导致性能问题,因此应该合理权衡宏任务和微任务的使用,确保在不牺牲实时性的前提下提高效率。

utationObserver 的异步特性

开发者需要注意 MutationObserver 具有异步特性,不会阻塞主线程。这使得 MutationObserver 更适用于大规模、频繁的 DOM 操作,能够减少页面的卡顿和性能问题。

相关推荐
AlgorithmAce2 小时前
Live2D嵌入前端页面
前端
nameofworld2 小时前
前端面试笔试(六)
前端·javascript·面试·学习方法·递归回溯
前端fighter2 小时前
js基本数据新增的Symbol到底是啥呢?
前端·javascript·面试
流着口水看上帝2 小时前
JavaScript完整原型链
开发语言·javascript·原型模式
guokanglun2 小时前
JavaScript数据类型判断之Object.prototype.toString.call() 的详解
开发语言·javascript·原型模式
GISer_Jing2 小时前
从0开始分享一个React项目:React-ant-admin
前端·react.js·前端框架
川石教育3 小时前
Vue前端开发子组件向父组件传参
前端·vue.js·前端开发·vue前端开发·vue组件传参
Embrace9243 小时前
为什么 Vue2会出现数据更新视图不更新 Vue3不会出现
javascript·vue.js·ecmascript
qq_415628173 小时前
bpmn.js显示流程图
javascript·vue.js·流程图
GISer_Jing3 小时前
Vue前端进阶面试题目(二)
前端·vue.js·面试