Framework
Version
Debouncer API Referenz
Throttler API Referenz
Rate Limiter API Referenz
Queue API Referenz
Batcher API Referenz

Async Throttling-Anleitung

Alle Kernkonzepte aus dem Throttling Guide gelten auch für asynchrones Throttling.

Wann asynchrones Throttling verwenden

Normalerweise können Sie einfach den normalen synchronen Throttler verwenden, und er funktioniert auch mit asynchronen Funktionen. Für fortgeschrittene Anwendungsfälle, wie z. B. wenn Sie den Rückgabewert einer gedrosselten Funktion verwenden möchten (anstatt nur einen setState-Nebeneffekt aufzurufen) oder Ihre Fehlerbehandlungslogik in den Throttler legen möchten, können Sie den asynchronen Throttler verwenden.

Asynchrones Throttling in TanStack Pacer

TanStack Pacer bietet asynchrones Throttling über die Klasse AsyncThrottler und die Funktion asyncThrottle.

Grundlegendes Beispiel

Hier ist ein einfaches Beispiel, das zeigt, wie der asynchrone Throttler für eine Suchoperation verwendet wird

ts
const throttledSearch = asyncThrottle(
  async (searchTerm: string) => {
    const results = await fetchSearchResults(searchTerm)
    return results
  },
  {
    wait: 500,
    onSuccess: (results, args, throttler) => {
      console.log('Search succeeded:', results)
      console.log('Search arguments:', args)
    },
    onError: (error, args, throttler) => {
      console.error('Search failed:', error)
      console.log('Failed arguments:', args)
    }
  }
)

// Usage
try {
  const results = await throttledSearch('query')
  // Handle successful results
} catch (error) {
  // Handle errors if no onError handler was provided
  console.error('Search failed:', error)
}
const throttledSearch = asyncThrottle(
  async (searchTerm: string) => {
    const results = await fetchSearchResults(searchTerm)
    return results
  },
  {
    wait: 500,
    onSuccess: (results, args, throttler) => {
      console.log('Search succeeded:', results)
      console.log('Search arguments:', args)
    },
    onError: (error, args, throttler) => {
      console.error('Search failed:', error)
      console.log('Failed arguments:', args)
    }
  }
)

// Usage
try {
  const results = await throttledSearch('query')
  // Handle successful results
} catch (error) {
  // Handle errors if no onError handler was provided
  console.error('Search failed:', error)
}

Hinweis: Bei der Verwendung von React bevorzugen Sie den Hook useAsyncThrottledCallback gegenüber der Funktion asyncThrottle für eine bessere Integration mit dem Lebenszyklus von React und die automatische Bereinigung.

Wesentliche Unterschiede zum synchronen Throttling

1. Handhabung des Rückgabewerts

Im Gegensatz zum synchronen Throttler, der void zurückgibt, ermöglicht die asynchrone Version, den Rückgabewert Ihrer gedrosselten Funktion zu erfassen und zu verwenden. Die Methode maybeExecute gibt ein Promise zurück, das mit dem Rückgabewert der Funktion aufgelöst wird. So können Sie auf das Ergebnis warten und es entsprechend behandeln.

2. Fehlerbehandlung

Der asynchrone Throttler bietet robuste Fehlerbehandlungsfunktionen

  • Wenn Ihre gedrosselte Funktion einen Fehler auslöst und kein onError-Handler bereitgestellt wird, wird der Fehler ausgelöst und zum Aufrufer weitergegeben.
  • Wenn Sie einen onError-Handler bereitstellen, werden Fehler abgefangen und an den Handler übergeben, anstatt ausgelöst zu werden.
  • Die Option throwOnError kann verwendet werden, um das Fehler-Auslöseverhalten zu steuern
    • Wenn true (Standard, wenn kein onError-Handler vorhanden ist), werden Fehler ausgelöst
    • Wenn false (Standard, wenn ein onError-Handler vorhanden ist), werden Fehler geschluckt
    • Kann explizit gesetzt werden, um diese Standardeinstellungen zu überschreiben
  • Sie können Fehlerzähler mit throttler.store.state.errorCount verfolgen und den Ausführungsstatus mit throttler.store.state.isExecuting überprüfen.
  • Der Throttler behält seinen Zustand bei und kann auch nach einem Fehler weiter verwendet werden

3. Unterschiedliche Callbacks

Die Klasse AsyncThrottler unterstützt die folgenden Rückrufe:

  • onSuccess: Wird nach jeder erfolgreichen Ausführung aufgerufen und liefert das Ergebnis, die Argumente, die ausgeführt wurden, und die Throttler-Instanz.
  • onSettled: Wird nach jeder Ausführung (erfolgreich oder fehlerhaft) aufgerufen und liefert die ausgeführten Argumente und die Throttler-Instanz.
  • onError: Wird aufgerufen, wenn die asynchrone Funktion einen Fehler auslöst, und liefert den Fehler, die Argumente, die den Fehler verursacht haben, und die Throttler-Instanz.

Beispiel

ts
const asyncThrottler = new AsyncThrottler(async (value) => {
  await saveToAPI(value)
}, {
  wait: 500,
  onSuccess: (result, args, throttler) => {
    // Called after each successful execution
    console.log('Async function executed', throttler.store.state.successCount)
    console.log('Executed arguments:', args)
  },
  onSettled: (args, throttler) => {
    // Called after each execution attempt
    console.log('Async function settled', throttler.store.state.settleCount)
    console.log('Settled arguments:', args)
  },
  onError: (error, args, throttler) => {
    // Called if the async function throws an error
    console.error('Async function failed:', error)
    console.log('Failed arguments:', args)
  }
})
const asyncThrottler = new AsyncThrottler(async (value) => {
  await saveToAPI(value)
}, {
  wait: 500,
  onSuccess: (result, args, throttler) => {
    // Called after each successful execution
    console.log('Async function executed', throttler.store.state.successCount)
    console.log('Executed arguments:', args)
  },
  onSettled: (args, throttler) => {
    // Called after each execution attempt
    console.log('Async function settled', throttler.store.state.settleCount)
    console.log('Settled arguments:', args)
  },
  onError: (error, args, throttler) => {
    // Called if the async function throws an error
    console.error('Async function failed:', error)
    console.log('Failed arguments:', args)
  }
})

4. Sequenzielle Ausführung

Da die Methode maybeExecute des Throttlers ein Promise zurückgibt, können Sie wählen, jede Ausführung abzuwarten, 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, wenn Sie mit Operationen zu tun haben, die von den Ergebnissen früherer Aufrufe abhängen, oder wenn die Aufrechterhaltung der Datenkonsistenz entscheidend 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.

Dynamische Optionen und Aktivierung/Deaktivierung

Genau wie der synchrone Throttler unterstützt der asynchrone Throttler dynamische Optionen für wait und enabled, die Funktionen sein können, die die Throttler-Instanz erhalten. Dies ermöglicht ein hochentwickeltes, laufzeitadaptives Throttling-Verhalten.

Ausstehende Ausführungen abbrechen

Der asynchrone Throttler unterstützt das Leeren ausstehender Ausführungen, um sie sofort auszulösen

ts
const asyncThrottler = new AsyncThrottler(asyncFn, { wait: 1000 })

asyncThrottler.maybeExecute('some-arg')
console.log(asyncThrottler.store.state.isPending) // true

// Flush immediately instead of waiting
asyncThrottler.flush()
console.log(asyncThrottler.store.state.isPending) // false
const asyncThrottler = new AsyncThrottler(asyncFn, { wait: 1000 })

asyncThrottler.maybeExecute('some-arg')
console.log(asyncThrottler.store.state.isPending) // true

// Flush immediately instead of waiting
asyncThrottler.flush()
console.log(asyncThrottler.store.state.isPending) // false

Zustandsverwaltung

Die Klasse AsyncThrottler verwendet TanStack Store für reaktives Zustandsmanagement und bietet Echtzeit-Zugriff auf den Ausführungsstatus, die Fehlerverfolgung und Zeitinformationen. Der gesamte Zustand wird in einem TanStack Store gespeichert und kann über asyncThrottler.store.state abgerufen werden. Wenn Sie jedoch einen Framework-Adapter wie React oder Solid verwenden, sollten Sie den Zustand nicht von hier abrufen. Stattdessen lesen Sie den Zustand aus asyncThrottler.state und stellen eine Selektor-Callback als 3. Argument für den Hook useAsyncThrottler bereit, um die Zustandsverfolgung zu aktivieren, wie unten gezeigt.

Zustandsselektor (Framework-Adapter)

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 throttler.state leer ({}), da der Selektor standardmäßig leer ist. Hier wird reaktiver Zustand von einem TanStack Store useStore gespeichert. Sie müssen die Zustandsverfolgung aktivieren, indem Sie eine Selektorfunktion bereitstellen.

ts
// Default behavior - no reactive state subscriptions
const asyncThrottler = useAsyncThrottler(asyncFn, { wait: 500 })
console.log(asyncThrottler.state) // {}

// Opt-in to re-render when isExecuting changes
const asyncThrottler = useAsyncThrottler(
  asyncFn, 
  { wait: 500 },
  (state) => ({ isExecuting: state.isExecuting })
)
console.log(asyncThrottler.state.isExecuting) // Reactive value

// Multiple state properties
const asyncThrottler = useAsyncThrottler(
  asyncFn,
  { wait: 500 },
  (state) => ({
    isExecuting: state.isExecuting,
    successCount: state.successCount,
    errorCount: state.errorCount
  })
)
// Default behavior - no reactive state subscriptions
const asyncThrottler = useAsyncThrottler(asyncFn, { wait: 500 })
console.log(asyncThrottler.state) // {}

// Opt-in to re-render when isExecuting changes
const asyncThrottler = useAsyncThrottler(
  asyncFn, 
  { wait: 500 },
  (state) => ({ isExecuting: state.isExecuting })
)
console.log(asyncThrottler.state.isExecuting) // Reactive value

// Multiple state properties
const asyncThrottler = useAsyncThrottler(
  asyncFn,
  { wait: 500 },
  (state) => ({
    isExecuting: state.isExecuting,
    successCount: state.successCount,
    errorCount: state.errorCount
  })
)

Anfangszustand

Sie können anfängliche Zustandswerte beim Erstellen eines asynchronen Throttlers angeben. Dies wird häufig verwendet, um Zustände aus persistentem Speicher wiederherzustellen

ts
// Load initial state from localStorage
const savedState = localStorage.getItem('async-throttler-state')
const initialState = savedState ? JSON.parse(savedState) : {}

const asyncThrottler = new AsyncThrottler(asyncFn, {
  wait: 500,
  initialState
})
// Load initial state from localStorage
const savedState = localStorage.getItem('async-throttler-state')
const initialState = savedState ? JSON.parse(savedState) : {}

const asyncThrottler = new AsyncThrottler(asyncFn, {
  wait: 500,
  initialState
})

Zustandsänderungen abonnieren

Der Store ist reaktiv und unterstützt Abonnements

ts
const asyncThrottler = new AsyncThrottler(asyncFn, { wait: 500 })

// Subscribe to state changes
const unsubscribe = asyncThrottler.store.subscribe((state) => {
  // do something with the state like persist it to localStorage
})

// Unsubscribe when done
unsubscribe()
const asyncThrottler = new AsyncThrottler(asyncFn, { wait: 500 })

// Subscribe to state changes
const unsubscribe = asyncThrottler.store.subscribe((state) => {
  // do something with the state like persist it to localStorage
})

// Unsubscribe when done
unsubscribe()

Hinweis: Dies ist unnötig, wenn Sie einen Framework-Adapter verwenden, da der zugrunde liegende Hook useStore dies bereits tut. Sie können auch useStore von TanStack Store importieren und verwenden, um throttler.store.state mit einem benutzerdefinierten Selektor zu einem reaktiven Zustand zu machen, wo immer Sie ihn benötigen.

Verfügbare Zustandseigenschaften

Die Klasse AsyncThrottlerState beinhaltet

  • errorCount: Anzahl der Funktionsausführungen, die zu Fehlern geführt haben
  • isExecuting: Gibt an, ob die gedrosselte Funktion derzeit asynchron ausgeführt wird
  • isPending: Ob der Throttler auf den Timeout wartet, um die Ausführung auszulösen
  • lastArgs: Die Argumente des letzten Aufrufs von maybeExecute
  • lastExecutionTime: Zeitstempel der letzten Funktionsausführung in Millisekunden
  • lastResult: Das Ergebnis der letzten erfolgreichen Funktionsausführung
  • maybeExecuteCount: Anzahl der Aufrufe von maybeExecute
  • nextExecutionTime: Zeitstempel, wann die nächste Ausführung erfolgen kann, in Millisekunden
  • settleCount: Anzahl der abgeschlossenen Funktionsausführungen (entweder erfolgreich oder mit Fehlern)
  • status: Aktueller Ausführungsstatus ('disabled' | 'idle' | 'pending' | 'executing' | 'settled')
  • successCount: Anzahl der Funktionsausführungen, die erfolgreich abgeschlossen wurden

Framework-Adapter

Jeder Framework-Adapter bietet Hooks, die auf der Kernfunktionalität des asynchronen Throttlings aufbauen, um sich in das Zustandsmanagementsystem des Frameworks zu integrieren. Hooks wie createAsyncThrottler, useAsyncThrottledCallback oder ähnliche sind für jedes Framework verfügbar.


Für Kernkonzepte des Throttlings und synchrones Throttling siehe den Throttling Guide.

Unsere Partner
Code Rabbit
Unkey
Bytes abonnieren

Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.

Bytes

Kein Spam. Jederzeit kündbar.

Bytes abonnieren

Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.

Bytes

Kein Spam. Jederzeit kündbar.