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?

Amir Tugi
quelle

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

Martin
quelle
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)
  });
Hari Das
quelle
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.');
  });
pcasme
quelle
Froh dir zu helfen.
pcasme