Versprechen aufhebbar machen

Mar 21 2023
Dies ist ein zweiteiliger Artikel, in dem wir uns zunächst darauf konzentrieren, die Grundlagen für die Verwendung der Suspense-API zu verstehen. Im nächsten Teil besprechen wir die Verwendung der New Suspense-Hooks für Meteor. Ich erkläre Ihnen, wie Sie Ihre Versprechen in den Spannungsmodus versetzen und was nötig ist, um dorthin zu gelangen.

Dies ist ein zweiteiliger Artikel, in dem wir uns zunächst auf das Verständnis der Grundlagen für die Verwendung der Suspense-API konzentrieren und im nächsten Teil die Verwendung der New Suspense-Hooks für Meteor besprechen .

Ich erkläre Ihnen, wie Sie Ihre Versprechen in den Spannungsmodus versetzen und was nötig ist, um dorthin zu gelangen.

Ich empfehle auf dieser Seite zwei Artikel zur Theorie, die mir geholfen haben zu verstehen, wie React mit asynchronen Werten umgeht. Einer stammt von Dan Abramov – Algebraic Effects for the Rest of Us und der andere von Radosław Miernik – On throwin React

Warum Spannung verwenden?

Wie dieser gute Artikel erklärt, bietet uns Suspense zwei großartige Funktionen:

  • Deklarativer Code bedeutet, dass React Suspense den Prozess des Schreibens von UI-Code vereinfacht, indem es Entwicklern ermöglicht, zu deklarieren, wie die UI aussehen soll, anstatt Code zu schreiben, der der UI Schritt für Schritt sagt, wie sie gerendert werden soll. Ein Beispiel für diese Funktion ist das Entfernen der Verwendungsvariablen isLoading. Indem Entwickler diese Variable über dem UI-Code platzieren, können sie sicherstellen, dass ihr Code mit der UI synchronisiert ist. Dadurch entfallen umständliche ifAussagen.
  • Bessere Endbenutzererfahrung mit Suspense. Sie können die neu hinzugefügte Concurrent-Rendering-Engine in React verwenden. Diese Suspense-Funktion gibt dem Endbenutzer ein besseres Gefühl dafür, wie die Benutzeroberfläche aussieht und funktioniert, da nur durch Reagieren aktualisiert wird, was benötigt wird.

Jetzt erkläre ich, wie das funktioniert. Zunächst benötigen Sie eine Cache-Karte, um Ihre Versprechen zu speichern. Da React das Versprechen aussetzt und dann erfüllt, benötigen Sie eine Möglichkeit, dieses spezifische Versprechen zu verfolgen (das war ein Teil, den ich nur schwer verstehen konnte, es muss jedes Mal genau das gleiche Versprechen sein). Wenn der angegebene Schlüssel keinen Wert enthält, erstellt der Hook mit this promiseund throwit einen Eintrag in der Map. Hier passiert die Magie. Der suspensifyHook sieht im ersten Durchlauf wie das folgende Snippet aus:

function suspensify<T>(key: string, promise: Promise<T> | null, deps: DependencyList = [], lifespan = 0): T {
  const cached = cacheMap.get(key)
	**//    ˆˆˆ this is undefined. all code below is not ran
  /* ... code ...*/
 const entry: Entry = {
    deps,
    promise: new Promise((resolve, reject) => { // here you work in your promise / waitable value. remember to set the result and error
      promise
        .then((result) => {
          entry.result = result
          resolve(result)
        })
        .catch((error) => {
          entry.error = error
          reject(error)
        })
    })
  }
  
  cacheMap.set(key, entry)
  throw entry.promise
// ˆˆˆˆthis is where we jump into the fallback
}

Nun, wenn der Hook erneut ausgeführt wird (ja, so funktioniert Suspense), gehen wir zu dem über, ifder über der Eintragserstellung stand:

function suspensify<T>(key: string, promise: Promise<T> | null, deps: DependencyList = [], lifespan = 0): T {
  const cached = cacheMap.get(key)
  //    ˆˆˆ now we have a value here
  useEffect(() =>
    () => {
      setTimeout(() => {
        if (cached !== undefined && isEqual(cached.deps, deps)) cacheMap.delete(key)
				// ˆˆˆˆclean when the hook unmounts.
      }, lifespan)
    }, [cached, key, ...deps])
  
  if (promise === null) return null // we talked about this one
  if (cached !== undefined) {
    if ('error' in cached) throw cached.error
              // ˆˆˆˆtrigger error boundary
    if ('result' in cached) {
      const result = cached.result as T
      setTimeout(() => {
        cacheMap.delete(key)
      }, lifespan)
      return result // resolve suspense
    }
    throw cached.promise // as we have not got any result or err we should wait a bit more
  }
  
/* ... code ...*/
}

Und nun haben Sie ein wenig darüber gelernt, wie Suspense funktioniert und wie Sie es heute nutzen können, um Ihre Versprechen einzulösen.

React Query unterstützt Suspense bereits und Relay ist unser herausragendstes Beispiel für die Suspense-API in der Praxis.

Wenn Sie sich für das, was Sie hier gesehen haben, interessieren und implementierte Versionen einer Bibliothek sehen möchten, die die Suspense-API verwenden, können Sie sich das nächste Kapitel dieser Artikelserie ansehen, in dem die neuen Suspense-Hooks für Meteor gezeigt werden .