批处理是一种强大的技术,用于将多个操作分组并作为一个单元进行处理。与确保每个操作单独处理的 队列 不同,批处理会收集项目并以可配置的组进行处理,从而提高效率并减少开销。本指南涵盖了 TanStack Pacer 的批处理概念。
批处理会随着时间的推移或达到一定大小时收集项目,然后一次性处理所有项目。这非常适合批量处理比逐个处理更有效的场景。批处理可以通过以下方式触发:
Batching (processing every 3 items or every 2 seconds)
Timeline: [1 second per tick]
Calls: ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️
Batch: [ABC] [] [DE] [] [FGH] []
Executed: ✅ ✅ ✅
[===============================]
^ Items are grouped and processed together
[Items accumulate] [Process batch] [Empty]
in batch as group batch
Batching (processing every 3 items or every 2 seconds)
Timeline: [1 second per tick]
Calls: ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️
Batch: [ABC] [] [DE] [] [FGH] []
Executed: ✅ ✅ ✅
[===============================]
^ Items are grouped and processed together
[Items accumulate] [Process batch] [Empty]
in batch as group batch
批处理的最佳使用场景是:
批处理可能不适合的情况是:
提示
如果您发现自己进行了可以合并的重复调用,批处理可以帮助您优化性能和资源使用。
TanStack Pacer 通过 Batcher 类和简单的 batch 函数提供批处理功能。两者都允许您收集项目并以可配置的批次进行处理。
batch
函数提供了一种创建批处理函数的方式。
import { batch } from '@tanstack/pacer'
// Create a batcher that processes up to 3 items or every 2 seconds
const processBatch = batch<number>(
(items) => {
// Process the batch
console.log('Processing batch:', items)
},
{
maxSize: 3, // Process when 3 items are collected
wait: 2000, // Or after 2 seconds, whichever comes first
onItemsChange: (batcher) => {
console.log('Current batch:', batcher.peekAllItems())
}
}
)
// Add items to be batched
processBatch(1)
processBatch(2)
processBatch(3) // Triggers batch processing
processBatch(4)
// Or wait 2 seconds for the next batch to process
import { batch } from '@tanstack/pacer'
// Create a batcher that processes up to 3 items or every 2 seconds
const processBatch = batch<number>(
(items) => {
// Process the batch
console.log('Processing batch:', items)
},
{
maxSize: 3, // Process when 3 items are collected
wait: 2000, // Or after 2 seconds, whichever comes first
onItemsChange: (batcher) => {
console.log('Current batch:', batcher.peekAllItems())
}
}
)
// Add items to be batched
processBatch(1)
processBatch(2)
processBatch(3) // Triggers batch processing
processBatch(4)
// Or wait 2 seconds for the next batch to process
注意: 在使用 React 时,优先使用 useBatchedCallback hook 而不是 batch 函数,以实现与 React 生命周期更好的集成和自动清理。
batch
函数返回一个函数,该函数将项目添加到批次中。批次会根据您的配置自动处理。
Batcher
类提供了对批处理行为的完全控制。
import { Batcher } from '@tanstack/pacer'
// Create a batcher that processes up to 5 items or every 3 seconds
const batcher = new Batcher<number>(
(items) => {
// Process the batch
console.log('Processing batch:', items)
},
{
maxSize: 5, // Process when 5 items are collected
wait: 3000, // Or after 3 seconds
getShouldExecute: (items, batcher) => items.includes(42), // Custom trigger
onItemsChange: (batcher) => {
console.log('Current batch:', batcher.peekAllItems())
}
}
)
// Add items to the batch
batcher.addItem(1)
batcher.addItem(2)
batcher.addItem(3)
// ...
// Manually process the current batch
batcher.execute()
// Control batching
batcher.stop() // Pause batching
batcher.start() // Resume batching
import { Batcher } from '@tanstack/pacer'
// Create a batcher that processes up to 5 items or every 3 seconds
const batcher = new Batcher<number>(
(items) => {
// Process the batch
console.log('Processing batch:', items)
},
{
maxSize: 5, // Process when 5 items are collected
wait: 3000, // Or after 3 seconds
getShouldExecute: (items, batcher) => items.includes(42), // Custom trigger
onItemsChange: (batcher) => {
console.log('Current batch:', batcher.peekAllItems())
}
}
)
// Add items to the batch
batcher.addItem(1)
batcher.addItem(2)
batcher.addItem(3)
// ...
// Manually process the current batch
batcher.execute()
// Control batching
batcher.stop() // Pause batching
batcher.start() // Resume batching
Batcher 选项允许您自定义批次的处理方式和时间。
Batcher
类提供了几个用于批次管理的 方法。
batcher.addItem(item) // Add an item to the batch
batcher.execute() // Manually process the current batch
batcher.stop() // Pause batching
batcher.start() // Resume batching
batcher.store.state.size // Get current batch size
batcher.store.state.isEmpty // Check if batch is empty
batcher.store.state.isRunning // Check if batcher is running
batcher.peekAllItems() // Get all items in the current batch
batcher.store.state.executionCount // Number of batches processed
batcher.store.state.totalItemsProcessed // Number of items processed
batcher.setOptions(opts) // Update batcher options
batcher.flush() // Flush pending batch immediately
batcher.addItem(item) // Add an item to the batch
batcher.execute() // Manually process the current batch
batcher.stop() // Pause batching
batcher.start() // Resume batching
batcher.store.state.size // Get current batch size
batcher.store.state.isEmpty // Check if batch is empty
batcher.store.state.isRunning // Check if batcher is running
batcher.peekAllItems() // Get all items in the current batch
batcher.store.state.executionCount // Number of batches processed
batcher.store.state.totalItemsProcessed // Number of items processed
batcher.setOptions(opts) // Update batcher options
batcher.flush() // Flush pending batch immediately
您可以使用 getShouldExecute 根据自定义逻辑触发批处理。
const batcher = new Batcher<number>(
(items) => console.log('Processing batch:', items),
{
getShouldExecute: (items) => items.includes(99),
}
)
batcher.addItem(1)
batcher.addItem(99) // Triggers batch processing immediately
const batcher = new Batcher<number>(
(items) => console.log('Processing batch:', items),
{
getShouldExecute: (items) => items.includes(99),
}
)
batcher.addItem(1)
batcher.addItem(99) // Triggers batch processing immediately
您可以在运行时更新 batcher 选项。
batcher.setOptions({
maxSize: 10,
wait: 1000,
})
const options = batcher.getOptions()
console.log(options.maxSize) // 10
batcher.setOptions({
maxSize: 10,
wait: 1000,
})
const options = batcher.getOptions()
console.log(options.maxSize) // 10
Batcher
类使用 TanStack Store 进行响应式状态管理,提供对批次状态、执行计数和处理状态的实时访问。所有状态都存储在 TanStack Store 中,可以通过 batcher.store.state 访问。但是,如果您使用的是 React 或 Solid 等框架适配器,则不应从此读取状态。而是应该从 batcher.state 读取状态,并为 useBatcher hook 的第三个参数提供一个选择器回调函数来选择加入状态跟踪,如下所示。
框架适配器支持一个 selector 参数,允许您指定哪些状态更改将触发重新渲染。通过防止不相关的状态更改导致不必要的重新渲染,这可以优化性能。
默认情况下,batcher.state 为空({}),因为选择器默认为空。 这是 TanStack Store 中的响应式状态 useStore 存储的位置。您必须提供一个选择器函数来选择加入状态跟踪。
// Default behavior - no reactive state subscriptions
const batcher = useBatcher(processFn, { maxSize: 5, wait: 1000 })
console.log(batcher.state) // {}
// Opt-in to re-render when size changes
const batcher = useBatcher(
processFn,
{ maxSize: 5, wait: 1000 },
(state) => ({ size: state.size })
)
console.log(batcher.state.size) // Reactive value
// Multiple state properties
const batcher = useBatcher(
processFn,
{ maxSize: 5, wait: 1000 },
(state) => ({
size: state.size,
executionCount: state.executionCount,
status: state.status
})
)
// Default behavior - no reactive state subscriptions
const batcher = useBatcher(processFn, { maxSize: 5, wait: 1000 })
console.log(batcher.state) // {}
// Opt-in to re-render when size changes
const batcher = useBatcher(
processFn,
{ maxSize: 5, wait: 1000 },
(state) => ({ size: state.size })
)
console.log(batcher.state.size) // Reactive value
// Multiple state properties
const batcher = useBatcher(
processFn,
{ maxSize: 5, wait: 1000 },
(state) => ({
size: state.size,
executionCount: state.executionCount,
status: state.status
})
)
您可以在创建 batcher 时提供初始状态值。这通常用于从持久存储中恢复状态。
// Load initial state from localStorage
const savedState = localStorage.getItem('batcher-state')
const initialState = savedState ? JSON.parse(savedState) : {}
const batcher = new Batcher(processFn, {
maxSize: 5,
wait: 1000,
initialState
})
// Load initial state from localStorage
const savedState = localStorage.getItem('batcher-state')
const initialState = savedState ? JSON.parse(savedState) : {}
const batcher = new Batcher(processFn, {
maxSize: 5,
wait: 1000,
initialState
})
Store 是响应式的并支持订阅
const batcher = new Batcher(processFn, { maxSize: 5, wait: 1000 })
// Subscribe to state changes
const unsubscribe = batcher.store.subscribe((state) => {
// do something with the state like persist it to localStorage
})
// Unsubscribe when done
unsubscribe()
const batcher = new Batcher(processFn, { maxSize: 5, wait: 1000 })
// Subscribe to state changes
const unsubscribe = batcher.store.subscribe((state) => {
// do something with the state like persist it to localStorage
})
// Unsubscribe when done
unsubscribe()
注意: 使用框架适配器时,这没有必要,因为底层的 useStore hook 已经完成了这项工作。如果需要,您也可以从 TanStack Store 导入和使用 useStore 将 batcher.store.state 变成带有自定义选择器的响应式状态。
BatcherState
包括:
batcher 支持刷新待处理的批次以立即触发处理。
const batcher = new Batcher(processFn, { maxSize: 10, wait: 5000 })
batcher.addItem('item1')
batcher.addItem('item2')
console.log(batcher.store.state.isPending) // true
// Flush immediately instead of waiting
batcher.flush()
console.log(batcher.store.state.isEmpty) // true (batch was processed)
const batcher = new Batcher(processFn, { maxSize: 10, wait: 5000 })
batcher.addItem('item1')
batcher.addItem('item2')
console.log(batcher.store.state.isPending) // true
// Flush immediately instead of waiting
batcher.flush()
console.log(batcher.store.state.isEmpty) // true (batch was processed)
每个框架适配器都在 batcher 类之上构建了便捷的 hook 和函数。诸如 useBatcher 或 createBatcher 等 hook 是小的包装器,可以减少您为某些常见用例编写代码所需的样板代码。
有关异步批处理,请参阅 异步批处理指南。
您的每周 JavaScript 资讯。每周一免费发送给超过 10 万开发者。