全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-20 8 分钟 ✍️ juanwangdev

nextTick实现

nextTick基于异步任务队列与微任务实现,将回调延迟到下次DOM更新循环结束后执行。

核心机制

JavaScript
const callbacks = []
let pending = false

function flushCallbacks() {
  pending = false
  const copies = callbacks.slice(0)
  callbacks.length = 0
  for (let i = 0; i < copies.length; i++) {
    copies[i]()
  }
}

使用副本执行防止执行期间新回调加入导致无限循环。

微任务降级策略

JavaScript
let timerFunc

// 优先使用Promise
if (typeof Promise !== 'undefined') {
  const p = Promise.resolve()
  timerFunc = () => {
    p.then(flushCallbacks)
  }
}
// 降级到MutationObserver
else if (typeof MutationObserver !== 'undefined') {
  let counter = 1
  const observer = new MutationObserver(flushCallbacks)
  const textNode = document.createTextNode(String(counter))
  observer.observe(textNode, { characterData: true })
  timerFunc = () => {
    counter = (counter + 1) % 2
    textNode.data = String(counter)
  }
}
// 最终降级setTimeout
else {
  timerFunc = () => {
    setTimeout(flushCallbacks, 0)
  }
}

优先微任务(Promise),降级到MutationObserver,最终降级到setTimeout。

nextTick API

JavaScript
export function nextTick(cb, ctx) {
  let _resolve
  callbacks.push(() => {
    if (cb) {
      cb.call(ctx)
    } else if (_resolve) {
      _resolve(ctx)
    }
  })
  
  if (!pending) {
    pending = true
    timerFunc()
  }
  
  if (!cb && typeof Promise !== 'undefined') {
    return new Promise(resolve => {
      _resolve = resolve
    })
  }
}

支持回调和Promise两种调用方式,同一tick内多次调用只触发一次异步任务。

与响应式系统配合

JavaScript
// Vue更新流程
function queueWatcher(watcher) {
  const id = watcher.id
  if (has[id] == null) {
    has[id] = true
    queue.push(watcher)
    if (!waiting) {
      waiting = true
      nextTick(flushSchedulerQueue)
    }
  }
}

watcher更新队列通过nextTick批量执行,避免重复渲染。

异步更新队列

JavaScript
// 数据变化
this.count++        // 触发setter
this.count++        // 再次触发setter
this.count++        // 再次触发setter

// DOM不会立即更新
console.log(this.$el.textContent)  // 还是旧值

nextTick(() => {
  console.log(this.$el.textContent)  // 更新后的值
})

同一tick内多次数据变更,只在nextTick统一更新DOM。

执行时机

JavaScript
// 同步代码执行
this.msg = 'new'

// 微任务队列: flushCallbacks
//   -> 执行所有nextTick回调
//   -> flushSchedulerQueue (DOM更新)

// 宏任务队列: (如果使用setTimeout降级)
//   -> 延迟执行

微任务优先级高于宏任务,Promise.then在DOM更新前执行。

要点总结

  • nextTick基于微任务(Promise)实现,降级到MutationObserver/setTimeout
  • 使用 callbacks 队列收集回调,pending 标记防止重复触发
  • 执行时使用副本防止执行期间新回调加入导致无限循环
  • 与watcher队列配合实现批量DOM更新
  • 支持回调函数和Promise两种调用方式
  • 同一tick内多次数据变更只触发一次DOM更新

📝 发现内容有误?点击此处直接编辑

← 上一篇 keep-alive原理
下一篇 → 事件系统底层实现
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库