框架
版本
Debouncer API 参考
Throttler API 参考
速率限制器 API 参考
队列 API 参考
批处理器 API 参考
批处理器示例

节流指南

速率限制、节流和防抖是控制函数执行频率的三种不同方法。每种技术以不同的方式阻止执行,使其具有“有损性”——这意味着当函数调用过于频繁时,某些函数调用将不会执行。了解何时使用每种方法对于构建高性能和可靠的应用程序至关重要。本指南将介绍 TanStack Pacer 的节流概念。

节流概念

节流确保函数执行在时间上均匀分布。与允许突发执行达到限制的速率限制或等待活动停止的防抖不同,节流通过在调用之间强制执行一致的延迟来创建更平滑的执行模式。如果将节流设置为每秒执行一次,则无论请求调用的速度有多快,调用都将均匀分布。

节流可视化

text
节流 (每 3 个滴答执行一次)
时间轴: [每个滴答 1 秒]
调用:        ⬇️  ⬇️  ⬇️           ⬇️  ⬇️  ⬇️  ⬇️             ⬇️
已执行:     ✅  ❌  ⏳  ->   ✅  ❌  ❌  ❌  ✅             ✅
             [=================================================================]
             ^ 每 3 个滴答只允许一次执行,
               无论进行多少次调用

             [第一次突发]    [更多调用]              [间隔调用]
             首先执行        等待期后执行             每次等待期过后执行
             然后节流
节流 (每 3 个滴答执行一次)
时间轴: [每个滴答 1 秒]
调用:        ⬇️  ⬇️  ⬇️           ⬇️  ⬇️  ⬇️  ⬇️             ⬇️
已执行:     ✅  ❌  ⏳  ->   ✅  ❌  ❌  ❌  ✅             ✅
             [=================================================================]
             ^ 每 3 个滴答只允许一次执行,
               无论进行多少次调用

             [第一次突发]    [更多调用]              [间隔调用]
             首先执行        等待期后执行             每次等待期过后执行
             然后节流

何时使用节流

当你需要一致、可预测的执行时序时,节流特别有效。这使其非常适合处理频繁的事件或更新,在这些情况下,你希望获得平滑、受控的行为。

何时不使用节流

在以下情况下,节流可能不是最佳选择:

  • 你想等待活动停止(改用防抖
  • 你不能错过任何执行(改用队列

Tip

当你需要平滑、一致的执行时序时,节流通常是最佳选择。与速率限制相比,它提供了更可预测的执行模式,并且比防抖提供更即时的反馈。

TanStack Pacer 中的节流

TanStack Pacer 提供同步和异步节流。本指南介绍同步 Throttler 类和 throttle 函数。有关异步节流,请参阅异步节流指南

throttle 的基本用法

throttle 函数是向任何函数添加节流的最简单方法:

ts
import { throttle } from '@tanstack/pacer'

// 将 UI 更新节流为每 200 毫秒一次
const throttledUpdate = throttle(
  (value: number) => updateProgressBar(value),
  {
    wait: 200,
  }
)

// 在快速循环中,每 200 毫秒仅执行一次
for (let i = 0; i < 100; i++) {
  throttledUpdate(i) // 许多调用被节流
}
import { throttle } from '@tanstack/pacer'

// 将 UI 更新节流为每 200 毫秒一次
const throttledUpdate = throttle(
  (value: number) => updateProgressBar(value),
  {
    wait: 200,
  }
)

// 在快速循环中,每 200 毫秒仅执行一次
for (let i = 0; i < 100; i++) {
  throttledUpdate(i) // 许多调用被节流
}

Throttler 类的高级用法

要对节流行为进行更多控制,可以直接使用 Throttler 类:

ts
import { Throttler } from '@tanstack/pacer'

const updateThrottler = new Throttler(
  (value: number) => updateProgressBar(value),
  { wait: 200 }
)

// 获取有关执行状态的信息
console.log(updateThrottler.getExecutionCount()) // 成功执行的次数
console.log(updateThrottler.getLastExecutionTime()) // 上次执行的时间戳

// 取消任何待处理的执行
updateThrottler.cancel()
import { Throttler } from '@tanstack/pacer'

const updateThrottler = new Throttler(
  (value: number) => updateProgressBar(value),
  { wait: 200 }
)

// 获取有关执行状态的信息
console.log(updateThrottler.getExecutionCount()) // 成功执行的次数
console.log(updateThrottler.getLastExecutionTime()) // 上次执行的时间戳

// 取消任何待处理的执行
updateThrottler.cancel()

前沿和后沿执行

同步节流器支持前沿和后沿执行:

ts
const throttledFn = throttle(fn, {
  wait: 200,
  leading: true,   // 首次调用时执行 (默认)
  trailing: true,  // 等待期后执行 (默认)
})
const throttledFn = throttle(fn, {
  wait: 200,
  leading: true,   // 首次调用时执行 (默认)
  trailing: true,  // 等待期后执行 (默认)
})
  • leading: true (默认) - 首次调用时立即执行
  • leading: false - 跳过首次调用,等待后沿执行
  • trailing: true (默认) - 等待期后执行最后一次调用
  • trailing: false - 如果在等待期内,则跳过最后一次调用

常见模式:

  • { leading: true, trailing: true } - 默认,响应最快
  • { leading: false, trailing: true } - 延迟所有执行
  • { leading: true, trailing: false } - 跳过排队的执行

启用/禁用

Throttler 类通过 enabled 选项支持启用/禁用。使用 setOptions 方法,可以随时启用/禁用节流器:

ts
const throttler = new Throttler(fn, { wait: 200, enabled: false }) // 默认禁用
throttler.setOptions({ enabled: true }) // 随时启用
const throttler = new Throttler(fn, { wait: 200, enabled: false }) // 默认禁用
throttler.setOptions({ enabled: true }) // 随时启用

enabled 选项也可以是一个返回布尔值的函数,允许根据运行时条件动态启用/禁用:

ts
const throttler = new Throttler(fn, {
  wait: 200,
  enabled: (throttler) => {
    return throttler.getExecutionCount() < 50 // 执行 50 次后禁用
  }
})
const throttler = new Throttler(fn, {
  wait: 200,
  enabled: (throttler) => {
    return throttler.getExecutionCount() < 50 // 执行 50 次后禁用
  }
})

如果你正在使用框架适配器,其中节流器选项是响应式的,则可以将 enabled 选项设置为条件值以动态启用/禁用节流器。但是,如果你直接使用 throttle 函数或 Throttler 类,则必须使用 setOptions 方法更改 enabled 选项,因为传递的选项实际上是传递给 Throttler 类的构造函数的。

动态选项

Throttler 中的几个选项通过接收节流器实例的回调函数支持动态值:

ts
const throttler = new Throttler(fn, {
  // 根据执行计数动态调整等待时间
  wait: (throttler) => {
    return throttler.getExecutionCount() * 100 // 每次执行增加等待时间
  },
  // 根据执行计数动态调整启用状态
  enabled: (throttler) => {
    return throttler.getExecutionCount() < 50 // 执行 50 次后禁用
  }
})
const throttler = new Throttler(fn, {
  // 根据执行计数动态调整等待时间
  wait: (throttler) => {
    return throttler.getExecutionCount() * 100 // 每次执行增加等待时间
  },
  // 根据执行计数动态调整启用状态
  enabled: (throttler) => {
    return throttler.getExecutionCount() < 50 // 执行 50 次后禁用
  }
})

以下选项支持动态值:

  • enabled:可以是布尔值或返回布尔值的函数
  • wait:可以是数字或返回数字的函数

这允许实现适应运行时条件的复杂节流行为。

回调选项

同步 Throttler 支持以下回调:

ts
const throttler = new Throttler(fn, {
  wait: 200,
  onExecute: (throttler) => {
    // 每次成功执行后调用
    console.log('函数已执行', throttler.getExecutionCount())
  }
})
const throttler = new Throttler(fn, {
  wait: 200,
  onExecute: (throttler) => {
    // 每次成功执行后调用
    console.log('函数已执行', throttler.getExecutionCount())
  }
})

onExecute 回调在节流函数每次成功执行后调用,可用于跟踪执行、更新 UI 状态或执行清理操作。


有关异步节流(例如 API 调用、异步操作),请参阅异步节流指南