Skip to content

Schleifengenerierungs Creation Functions ​

Creation Functions zur Darstellung von Schleifenverarbeitungen wie for- oder while-Schleifen als Observable.

Was sind Schleifengenerierungs Creation Functions ​

Schleifengenerierungs Creation Functions ermöglichen die reaktive Implementierung von Wiederholungsverarbeitungen. Durch den Ersatz traditioneller imperativer Schleifen (for-Anweisungen, while-Anweisungen) durch deklarative Observable-Streams wird eine flexible Verarbeitung in Kombination mit RxJS-Operator-Ketten möglich.

In der folgenden Tabelle können Sie die Eigenschaften und Anwendungsfälle der einzelnen Creation Functions überprüfen.

Wichtige Schleifengenerierungs Creation Functions ​

FunctionBeschreibungAnwendungsfälle
rangeGeneriert einen Zahlenbereich (wie for-Schleife)Sequenzgenerierung, Stapelverarbeitung
generateUniverselle Schleifengenerierung (wie while-Schleife)Bedingte Wiederholung, komplexe Zustandsübergänge

Auswahlkriterien ​

Die Auswahl von Schleifengenerierungs Creation Functions erfolgt nach folgenden Gesichtspunkten:

1. Generierungsmuster ​

  • Zahlenfolge: range() - Einfache Sequenzgenerierung durch Angabe von Start- und Endwert
  • Komplexe Bedingungen: generate() - Freie Kontrolle über Anfangswert, Bedingung, Iteration und Ergebnisauswahl

2. Schleifentyp ​

  • for-Schleifen-ähnlich: range() - for (let i = start; i <= end; i++)
  • while-Schleifen-ähnlich: generate() - while (condition) { ... }

3. Flexibilität ​

  • Einfach ausreichend: range() - Wenn eine Zahlenfolge benötigt wird
  • Erweiterte Kontrolle erforderlich: generate() - Benutzerdefinierte Zustandsverwaltung, bedingte Verzweigung, Schrittsteuerung

Praktische Anwendungsbeispiele ​

range() - Sequenzgenerierung ​

Für einfache Sequenzgenerierung ist range() optimal.

typescript
import { range, map } from 'rxjs';
// Generiert Sequenz von 1 bis 5
range(1, 5).subscribe(console.log);
// Ausgabe: 1, 2, 3, 4, 5

// Anwendung in Stapelverarbeitung
range(0, 10).pipe(
  map(i => `Verarbeitung${i + 1}`)
).subscribe(console.log);
// Ausgabe: Verarbeitung1, Verarbeitung2, ..., Verarbeitung10

generate() - Bedingte Schleife ​

Für komplexe Bedingungen oder benutzerdefinierte Zustandsverwaltung verwenden Sie generate().

typescript
import { generate } from 'rxjs';

// Fibonacci-Folge generieren (erste 10 Elemente)
generate(
  { current: 0, next: 1, count: 0 },  // Anfangszustand
  state => state.count < 10,           // Fortsetzungsbedingung
  state => ({                          // Zustandsaktualisierung
    current: state.next,
    next: state.current + state.next,
    count: state.count + 1
  }),
  state => state.current               // Ergebnisauswahl
).subscribe(console.log);
// Ausgabe: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34

Vergleich mit imperativen Schleifen ​

Vergleich zwischen traditionellen imperativen Schleifen und RxJS Schleifengenerierungs Creation Functions.

Imperative for-Schleife ​

typescript
// Traditionelle for-Schleife
const results: number[] = [];
for (let i = 1; i <= 5; i++) {
  results.push(i * 2);
}
console.log(results); // [2, 4, 6, 8, 10]

Deklaratives range() ​

typescript
import { range, map, toArray } from 'rxjs';
// RxJS range()
range(1, 5).pipe(
  map(i => i * 2),
  toArray()
).subscribe(console.log); // [2, 4, 6, 8, 10]

TIP

Vorteile des deklarativen Ansatzes:

  • Verbesserte Lesbarkeit durch Pipeline-Verarbeitung
  • Einheitliche Fehlerbehandlung
  • Einfache Kombination mit asynchroner Verarbeitung
  • Einfaches Abbrechen oder Unterbrechen (mit takeUntil() etc.)

Umwandlung von Cold zu Hot ​

Wie in der obigen Tabelle gezeigt, erzeugen alle Schleifengenerierungs Creation Functions Cold Observables. Bei jeder Subscription beginnt eine unabhängige Ausführung.

Durch Verwendung von Multicasting-Operatoren (share(), shareReplay() etc.) können Sie jedoch Cold Observables in Hot Observables umwandeln.

Praxisbeispiel: Berechnungsergebnisse teilen ​

typescript
import { range, map, share } from 'rxjs';
// ❄️ Cold - Unabhängige Berechnung pro Subscription
const cold$ = range(1, 1000).pipe(
  map(n => {
    console.log('Berechnung:', n);
    return n * n;
  })
);

cold$.subscribe(val => console.log('Subscriber1:', val));
cold$.subscribe(val => console.log('Subscriber2:', val));
// → Berechnung wird 2-mal ausgeführt (2000 Berechnungen)

// 🔥 Hot - Berechnungsergebnisse zwischen Subscribern teilen
const hot$ = range(1, 1000).pipe(
  map(n => {
    console.log('Berechnung:', n);
    return n * n;
  }),
  share()
);

hot$.subscribe(val => console.log('Subscriber1:', val));
hot$.subscribe(val => console.log('Subscriber2:', val));
// → Berechnung wird nur 1-mal ausgeführt (1000 Berechnungen)

TIP

Fälle, in denen Hot-Umwandlung erforderlich ist:

  • Teure Berechnungen an mehreren Stellen verwenden
  • Stapelverarbeitungsergebnisse über mehrere Komponenten teilen
  • Paginierungsergebnisse in mehreren UI-Komponenten anzeigen

Weitere Details siehe Basis-Erstellungs - Cold zu Hot Umwandlung.

Kombination mit asynchroner Verarbeitung ​

Schleifengenerierungs Creation Functions entfalten ihre volle Leistungsfähigkeit in Kombination mit asynchroner Verarbeitung.

Sequenzielle API-Aufrufe ​

typescript
import { range, of, Observable, concatMap, delay } from 'rxjs';
interface PageData {
  page: number;
  items: string[];
}

// Funktion zur Simulation des Seitenabrufs
function fetchPage(page: number): Observable<PageData> {
  return of({
    page,
    items: [`Daten${page}-1`, `Daten${page}-2`, `Daten${page}-3`]
  }).pipe(
    delay(300) // Simuliert API-Aufruf
  );
}

// Seiten 1 bis 10 sequenziell abrufen (mit 1 Sekunde Verzögerung zwischen Anfragen)
range(1, 10).pipe(
  concatMap(page =>
    fetchPage(page).pipe(delay(1000))
  )
).subscribe(
  data => console.log(`Seite ${data.page} abgerufen:`, data.items),
  err => console.error('Fehler:', err)
);

Anwendung in Retry-Logik ​

typescript
import { range, throwError, of, Observable, mergeMap, retry, delay } from 'rxjs';
// Funktion zur Simulation des Datenabrufs (scheitert zufällig)
function fetchData(): Observable<string> {
  const shouldFail = Math.random() > 0.6; // 40% Erfolgswahrscheinlichkeit

  return of(shouldFail).pipe(
    delay(200),
    mergeMap(fail =>
      fail
        ? throwError(() => new Error('Datenabruf fehlgeschlagen'))
        : of('Datenabruf erfolgreich')
    )
  );
}

function fetchWithRetry() {
  return fetchData().pipe(
    // Empfohlen ab RxJS 7.3+: retry({ count, delay })-Form
    retry({
      count: 3, // Maximal 3 Wiederholungen
      delay: (error, retryCount) => {
        console.log(`Wiederholung ${retryCount}/3`);
        // Exponentieller Backoff: 1s, 2s, 4s
        return range(0, 1).pipe(delay(Math.pow(2, retryCount - 1) * 1000));
      }
    })
  );
}

fetchWithRetry().subscribe({
  next: result => console.log('Ergebnis:', result),
  error: err => console.error('Fehler:', err.message)
});

// Beispielausgabe:
// Wiederholung 1/3
// Wiederholung 2/3
// Ergebnis: Datenabruf erfolgreich

Beziehung zu Pipeable Operators ​

Schleifengenerierungs Creation Functions haben keine direkten Entsprechungen als Pipeable Operators. Sie werden immer als Creation Functions verwendet.

Durch Kombination mit folgenden Operatoren sind jedoch erweiterte Verarbeitungen möglich:

Kombinations-OperatorZweck
map()Jeden Wert transformieren
filter()Nur Werte durchlassen, die Bedingung erfüllen
take(), skip()Anzahl der Werte kontrollieren
concatMap(), mergeMap()Asynchrone Verarbeitung für jeden Wert
toArray()Alle Werte in Array sammeln

Performance-Hinweise ​

Schleifengenerierungs Creation Functions emittieren Werte synchron, daher ist bei großen Datenmengen Vorsicht geboten.

WARNING

Umgang mit großen Datenmengen:

  • range(1, 1000000) emittiert alle Werte synchron und verbraucht Speicher
  • Bei Bedarf mit bufferCount() oder windowCount() puffern
  • Oder scheduled() verwenden, um asynchrone Ausführung mit Scheduler anzugeben
typescript
import { range, asyncScheduler, observeOn } from 'rxjs';
// Mit asynchronem Scheduler ausführen
range(1, 1000000).pipe(
  observeOn(asyncScheduler)
).subscribe(console.log);

Nächste Schritte ​

Um die detaillierte Funktionsweise und praktischen Beispiele jeder Creation Function zu lernen, klicken Sie auf die Links in der obigen Tabelle.

Durch das Studium von Basis-Erstellungs Creation Functions, Kombinations Creation Functions, Auswahl/Partitionierungs Creation Functions und Bedingte Verzweigungs Creation Functions können Sie ein Gesamtverständnis der Creation Functions erlangen.

Veröffentlicht unter CC-BY-4.0-Lizenz.