Alle Kernkonzepte aus dem Debouncing Guide gelten auch für asynchrone Debounce.
Normalerweise können Sie einfach den normalen synchronen Debouncer verwenden und er funktioniert mit asynchronen Funktionen. Für fortgeschrittene Anwendungsfälle, z. B. wenn Sie den Rückgabewert einer debounced Funktion verwenden möchten (anstatt nur einen setState-Seiteneffekt auszuführen) oder Ihre Fehlerbehandlungslogik in den Debouncer legen möchten, können Sie den asynchronen Debouncer verwenden.
TanStack Pacer bietet asynchrone Debounce über die Klasse AsyncDebouncer und die Funktion asyncDebounce.
Hier ist ein grundlegendes Beispiel, wie der asynchrone Debouncer für eine Suchoperation verwendet wird
const debouncedSearch = asyncDebounce(
async (searchTerm: string) => {
const results = await fetchSearchResults(searchTerm)
return results
},
{
wait: 500,
onSuccess: (results, args, debouncer) => {
console.log('Search succeeded:', results)
console.log('Search arguments:', args)
},
onError: (error, args, debouncer) => {
console.error('Search failed:', error)
console.log('Failed arguments:', args)
}
}
)
// Usage
try {
const results = await debouncedSearch('query')
// Handle successful results
} catch (error) {
// Handle errors if no onError handler was provided
console.error('Search failed:', error)
}
const debouncedSearch = asyncDebounce(
async (searchTerm: string) => {
const results = await fetchSearchResults(searchTerm)
return results
},
{
wait: 500,
onSuccess: (results, args, debouncer) => {
console.log('Search succeeded:', results)
console.log('Search arguments:', args)
},
onError: (error, args, debouncer) => {
console.error('Search failed:', error)
console.log('Failed arguments:', args)
}
}
)
// Usage
try {
const results = await debouncedSearch('query')
// Handle successful results
} catch (error) {
// Handle errors if no onError handler was provided
console.error('Search failed:', error)
}
Hinweis: Wenn Sie React verwenden, bevorzugen Sie den Hook useAsyncDebouncedCallback gegenüber der Funktion asyncDebounce, um eine bessere Integration mit dem Lebenszyklus von React und automatische Bereinigung zu gewährleisten.
Im Gegensatz zum synchronen Debouncer, der void zurückgibt, ermöglicht die asynchrone Version das Erfassen und Verwenden des Rückgabewerts Ihrer debounced Funktion. Die Methode maybeExecute gibt ein Promise zurück, das mit dem Rückgabewert der Funktion aufgelöst wird, sodass Sie das Ergebnis awaiten und entsprechend behandeln können.
Der asynchrone Debouncer bietet robuste Fehlerbehandlungsfunktionen
Der AsyncDebouncer unterstützt die folgenden Callbacks
Beispiel
const asyncDebouncer = new AsyncDebouncer(async (value) => {
await saveToAPI(value)
}, {
wait: 500,
onSuccess: (result, args, debouncer) => {
// Called after each successful execution
console.log('Async function executed', debouncer.store.state.successCount)
console.log('Executed arguments:', args)
},
onSettled: (args, debouncer) => {
// Called after each execution attempt
console.log('Async function settled', debouncer.store.state.settleCount)
console.log('Settled arguments:', args)
},
onError: (error) => {
// Called if the async function throws an error
console.error('Async function failed:', error)
}
})
const asyncDebouncer = new AsyncDebouncer(async (value) => {
await saveToAPI(value)
}, {
wait: 500,
onSuccess: (result, args, debouncer) => {
// Called after each successful execution
console.log('Async function executed', debouncer.store.state.successCount)
console.log('Executed arguments:', args)
},
onSettled: (args, debouncer) => {
// Called after each execution attempt
console.log('Async function settled', debouncer.store.state.settleCount)
console.log('Settled arguments:', args)
},
onError: (error) => {
// Called if the async function throws an error
console.error('Async function failed:', error)
}
})
Da die Methode maybeExecute des Debouncers ein Promise zurückgibt, können Sie jede Ausführung awaiten, bevor Sie die nächste starten. Dies gibt Ihnen die Kontrolle über die Ausführungsreihenfolge und stellt sicher, dass jeder Aufruf die aktuellsten Daten verarbeitet. Dies ist besonders nützlich bei Operationen, die von den Ergebnissen früherer Aufrufe abhängen oder wenn die Datenkonsistenz kritisch ist.
Wenn Sie beispielsweise das Profil eines Benutzers aktualisieren und dann sofort dessen aktualisierte Daten abrufen, können Sie die Aktualisierungsoperation awaiten, bevor Sie den Abruf starten.
Ähnlich wie der synchrone Debouncer unterstützt der asynchrone Debouncer dynamische Optionen für wait und enabled, die Funktionen sein können, die die Debouncer-Instanz erhalten. Dies ermöglicht ein ausgeklügeltes, laufzeitadaptives Debouncing-Verhalten.
Der asynchrone Debouncer unterstützt das Auslösen ausstehender Ausführungen, um sie sofort zu starten
const asyncDebouncer = new AsyncDebouncer(asyncFn, { wait: 1000 })
asyncDebouncer.maybeExecute('some-arg')
console.log(asyncDebouncer.store.state.isPending) // true
// Flush immediately instead of waiting
asyncDebouncer.flush()
console.log(asyncDebouncer.store.state.isPending) // false
const asyncDebouncer = new AsyncDebouncer(asyncFn, { wait: 1000 })
asyncDebouncer.maybeExecute('some-arg')
console.log(asyncDebouncer.store.state.isPending) // true
// Flush immediately instead of waiting
asyncDebouncer.flush()
console.log(asyncDebouncer.store.state.isPending) // false
Die Klasse AsyncDebouncer verwendet TanStack Store für reaktive Zustandsverwaltung und bietet Echtzeit-Zugriff auf den Ausführungsstatus, Fehlerverfolgung und Ausführungsstatistiken. Alle Zustände werden in einem TanStack Store gespeichert und können über asyncDebouncer.store.state abgerufen werden. Wenn Sie jedoch einen Framework-Adapter wie React oder Solid verwenden, sollten Sie den Zustand nicht von hier abrufen. Stattdessen rufen Sie den Zustand über asyncDebouncer.state ab und stellen zusätzlich einen Selektor-Callback als 3. Argument für den Hook useAsyncDebouncer bereit, um die Zustandsverfolgung zu aktivieren, wie unten gezeigt.
Framework-Adapter unterstützen ein selector-Argument, das es Ihnen ermöglicht, anzugeben, welche Zustandsänderungen Neu-Renderings auslösen. Dies optimiert die Leistung, indem unnötige Neu-Renderings bei irrelevanten Zustandsänderungen verhindert werden.
Standardmäßig ist debouncer.state leer ({}), da der Selektor standardmäßig leer ist. Hier werden reaktive Zustände aus einem TanStack Store useStore gespeichert. Sie müssen die Zustandsverfolgung aktivieren, indem Sie eine Selektorfunktion angeben.
// Default behavior - no reactive state subscriptions
const asyncDebouncer = useAsyncDebouncer(asyncFn, { wait: 500 })
console.log(asyncDebouncer.state) // {}
// Opt-in to re-render when isExecuting changes
const asyncDebouncer = useAsyncDebouncer(
asyncFn,
{ wait: 500 },
(state) => ({ isExecuting: state.isExecuting })
)
console.log(asyncDebouncer.state.isExecuting) // Reactive value
// Multiple state properties
const asyncDebouncer = useAsyncDebouncer(
asyncFn,
{ wait: 500 },
(state) => ({
isExecuting: state.isExecuting,
successCount: state.successCount,
errorCount: state.errorCount
})
)
// Default behavior - no reactive state subscriptions
const asyncDebouncer = useAsyncDebouncer(asyncFn, { wait: 500 })
console.log(asyncDebouncer.state) // {}
// Opt-in to re-render when isExecuting changes
const asyncDebouncer = useAsyncDebouncer(
asyncFn,
{ wait: 500 },
(state) => ({ isExecuting: state.isExecuting })
)
console.log(asyncDebouncer.state.isExecuting) // Reactive value
// Multiple state properties
const asyncDebouncer = useAsyncDebouncer(
asyncFn,
{ wait: 500 },
(state) => ({
isExecuting: state.isExecuting,
successCount: state.successCount,
errorCount: state.errorCount
})
)
Sie können Anfangswerte für den Zustand angeben, wenn Sie einen asynchronen Debouncer erstellen. Dies wird häufig verwendet, um den Zustand aus persistentem Speicher wiederherzustellen.
// Load initial state from localStorage
const savedState = localStorage.getItem('async-debouncer-state')
const initialState = savedState ? JSON.parse(savedState) : {}
const asyncDebouncer = new AsyncDebouncer(asyncFn, {
wait: 500,
initialState
})
// Load initial state from localStorage
const savedState = localStorage.getItem('async-debouncer-state')
const initialState = savedState ? JSON.parse(savedState) : {}
const asyncDebouncer = new AsyncDebouncer(asyncFn, {
wait: 500,
initialState
})
Der Store ist reaktiv und unterstützt Abonnements
const asyncDebouncer = new AsyncDebouncer(asyncFn, { wait: 500 })
// Subscribe to state changes
const unsubscribe = asyncDebouncer.store.subscribe((state) => {
// do something with the state like persist it to localStorage
})
// Unsubscribe when done
unsubscribe()
const asyncDebouncer = new AsyncDebouncer(asyncFn, { wait: 500 })
// Subscribe to state changes
const unsubscribe = asyncDebouncer.store.subscribe((state) => {
// do something with the state like persist it to localStorage
})
// Unsubscribe when done
unsubscribe()
Hinweis: Dies ist nicht erforderlich, wenn Sie einen Framework-Adapter verwenden, da der zugrundeliegende Hook useStore dies bereits tut. Sie können auch useStore von TanStack Store importieren und verwenden, um debouncer.store.state bei Bedarf mit einem benutzerdefinierten Selektor zu reaktiven Zuständen zu machen.
Die AsyncDebouncerState enthält
Jeder Framework-Adapter bietet Hooks, die auf der Kernfunktionalität der asynchronen Debounce aufbauen, um sich in das Zustandsverwaltungssystem des Frameworks zu integrieren. Hooks wie createAsyncDebouncer, useAsyncDebouncedCallback oder ähnliche sind für jedes Framework verfügbar.
Für Kernkonzepte der Debounce und synchrone Debounce siehe den Debouncing Guide.
Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.