速率限制、节流和防抖是控制函数执行频率的三种不同方法。每种技术以不同的方式阻止执行,使其具有“有损性”——这意味着当函数调用过于频繁时,某些函数调用将不会执行。了解何时使用每种方法对于构建高性能和可靠的应用程序至关重要。本指南将介绍 TanStack Pacer 的节流概念。
节流确保函数执行在时间上均匀分布。与允许突发执行达到限制的速率限制或等待活动停止的防抖不同,节流通过在调用之间强制执行一致的延迟来创建更平滑的执行模式。如果将节流设置为每秒执行一次,则无论请求调用的速度有多快,调用都将均匀分布。
节流 (每 3 个滴答执行一次)
时间轴: [每个滴答 1 秒]
调用: ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️
已执行: ✅ ❌ ⏳ -> ✅ ❌ ❌ ❌ ✅ ✅
[=================================================================]
^ 每 3 个滴答只允许一次执行,
无论进行多少次调用
[第一次突发] [更多调用] [间隔调用]
首先执行 等待期后执行 每次等待期过后执行
然后节流
节流 (每 3 个滴答执行一次)
时间轴: [每个滴答 1 秒]
调用: ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️
已执行: ✅ ❌ ⏳ -> ✅ ❌ ❌ ❌ ✅ ✅
[=================================================================]
^ 每 3 个滴答只允许一次执行,
无论进行多少次调用
[第一次突发] [更多调用] [间隔调用]
首先执行 等待期后执行 每次等待期过后执行
然后节流
当你需要一致、可预测的执行时序时,节流特别有效。这使其非常适合处理频繁的事件或更新,在这些情况下,你希望获得平滑、受控的行为。
在以下情况下,节流可能不是最佳选择:
Tip
当你需要平滑、一致的执行时序时,节流通常是最佳选择。与速率限制相比,它提供了更可预测的执行模式,并且比防抖提供更即时的反馈。
TanStack Pacer 提供同步和异步节流。本指南介绍同步 Throttler 类和 throttle 函数。有关异步节流,请参阅异步节流指南。
throttle 函数是向任何函数添加节流的最简单方法:
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 类:
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()
同步节流器支持前沿和后沿执行:
const throttledFn = throttle(fn, {
wait: 200,
leading: true, // 首次调用时执行 (默认)
trailing: true, // 等待期后执行 (默认)
})
const throttledFn = throttle(fn, {
wait: 200,
leading: true, // 首次调用时执行 (默认)
trailing: true, // 等待期后执行 (默认)
})
常见模式:
Throttler 类通过 enabled 选项支持启用/禁用。使用 setOptions 方法,可以随时启用/禁用节流器:
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 选项也可以是一个返回布尔值的函数,允许根据运行时条件动态启用/禁用:
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 中的几个选项通过接收节流器实例的回调函数支持动态值:
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 次后禁用
}
})
以下选项支持动态值:
这允许实现适应运行时条件的复杂节流行为。
同步 Throttler 支持以下回调:
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 调用、异步操作),请参阅异步节流指南。