Endlich beim Abonnieren zu beobachten


105

Nach diesem Artikel schließen sich onCompleteund onErrorFunktion der subscribegegenseitig aus.

Das heißt, entweder onErroroder onCompleteEreignisse werden in meinem ausgelöst subscribe.
Ich habe einen Logikblock, der ausgeführt werden muss, unabhängig davon, ob ich einen Fehler erhalte oder meinen Informationsdampf erfolgreich beendet habe.

Ich habe nach etwas wie finallyin Python gesucht , aber alles, was ich gefunden habe, ist, finallywas an das von mir erstellte Observable angehängt werden muss.

Aber ich möchte diese Logik nur dann ausführen, wenn ich mich anmelde und nachdem der Stream beendet wurde, ob erfolgreich oder mit einem Fehler.

Irgendwelche Ideen?

Antworten:


130

Die aktuelle "pipable" -Variante dieses Operators wird aufgerufen finalize()(seit RxJS 6). Der ältere und jetzt veraltete "Patch" -Operator wurde aufgerufen finally()(bis RxJS 5.5).

Ich denke, der finalize()Operator ist tatsächlich korrekt. Du sagst:

Führen Sie diese Logik nur aus, wenn ich mich anmelde und nachdem der Stream beendet wurde

Das ist kein Problem, denke ich. Sie können eine Single haben sourceund verwenden, finalize()bevor Sie sie abonnieren, wenn Sie möchten. Auf diese Weise müssen Sie nicht immer Folgendes verwenden finalize():

let source = new Observable(observer => {
  observer.next(1);
  observer.error('error message');
  observer.next(3);
  observer.complete();
}).pipe(
  publish(),
);

source.pipe(
  finalize(() => console.log('Finally callback')),
).subscribe(
  value => console.log('#1 Next:', value),
  error => console.log('#1 Error:', error),
  () => console.log('#1 Complete')
);

source.subscribe(
  value => console.log('#2 Next:', value),
  error => console.log('#2 Error:', error),
  () => console.log('#2 Complete')
);

source.connect();

Dies wird auf der Konsole gedruckt:

#1 Next: 1
#2 Next: 1
#1 Error: error message
Finally callback
#2 Error: error message

Jan 2019: Aktualisiert für RxJS 6


1
Interessant, dass es sich um das entgegengesetzte Muster von Versprechungen handelt, da die finally()Methode zuerst angehängt wird und das Abonnement zwangsläufig das Bestehen / Nichtbestehen erzwingt.
BradGreens

7
Ja, das ist schade. Man würde denken, dass der finallyBlock in Ihrem Code an letzter Stelle steht.
d512

Ich mochte das Versprechungssystem von Angular JS ... Wie d512 sagt, habe ich erwartet, dass "endlich" das letzte sein wird ...
Mag das

10
Ab RXJS 5.5 ist "finally" keine Observable-Methode mehr. Verwenden Sie stattdessen den Operator "finalize": source.pipe (finalize (() => console.log ('Endlich Rückruf'))). Subscribe (...); github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md
Stevethemacguy

Das Problem beim Finalisieren ist, dass es auf einen "complete ()" - Aufruf wartet. Was ist, wenn Sie ein endgültiges Ergebnis für jede Emission wünschen (wenn die beobachtbare Emission erfolgreich ist, tun Sie a , wenn es fehlerhaft ist, tun Sie stattdessen b . In beiden Fällen tun Sie c )?
Roberto Tomás

64

Das einzige, was für mich funktioniert hat, ist dies

fetchData()
  .subscribe(
    (data) => {
       //Called when success
     },
    (error) => {
       //Called when error
    }
  ).add(() => {
       //Called when operation is complete (both success and error)
  });

26

Ich verwende jetzt RxJS 5.5.7 in einer Angular-Anwendung und der finalizeOperator hat ein seltsames Verhalten für meinen Anwendungsfall, da er vor erfolgreichen oder fehlerhaften Rückrufen ausgelöst wird.

Einfaches Beispiel:

// Simulate an AJAX callback...
of(null)
  .pipe(
    delay(2000),
    finalize(() => {
      // Do some work after complete...
      console.log('Finalize method executed before "Data available" (or error thrown)');
    })
  )
  .subscribe(
      response => {
        console.log('Data available.');
      },
      err => {
        console.error(err);
      }
  );

Ich musste das addMedhod im Abonnement verwenden, um das zu erreichen, was ich will. Grundsätzlich erfolgt ein finallyRückruf nach den erfolgreichen oder fehlerhaften Rückrufen. Wie ein try..catch..finallyBlock oder eine Promise.finallyMethode.

Einfaches Beispiel:

// Simulate an AJAX callback...
of(null)
  .pipe(
    delay(2000)
  )
  .subscribe(
      response => {
        console.log('Data available.');
      },
      err => {
        console.error(err);
      }
  );
  .add(() => {
    // Do some work after complete...
    console.log('At this point the success or error callbacks has been completed.');
  });

Froh dir zu helfen.
pcasme
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.