javascript - RxJS - observable fullfører ikke når en feil oppstår
Når jeg lager en observable fra bunnen av, og observeren feiler, og deretter fullføres, blir aldri ferdig-delen av abonnementet kalt.
var observer = Rx.Observable.create(function(observer){
observer.onError(new Error('no!'));
observer.onCompleted();
})
observer.subscribe(
function(x) { console.log('succeeded with ' + x ) },
function(x) { console.log('errored with ' + x ) },
function() { console.log('completed') }
)
Utdataene er:
errored with Error: no!
Jeg vil forvente at det er:
errored with Error: no!
completed
Hvis jeg endrer koden for å kalle på onNext i stedet for onError, fullfører observable korrekt:
var observer = Rx.Observable.create(function(observer){
observer.onNext('Hi!');
observer.onCompleted();
})
observer.subscribe(
function(x) { console.log('succeeded with ' + x ) },
function(x) { console.log('errored with ' + x ) },
function() { console.log('completed') }
)
Jeg får den forventede utskriften:
succeeded with Hi!
completed
Hvorfor fullfører den ikke når en feil har oppstått?
Svar #1
Det er fordi en feil betyr fullføring, så tilbakekallet knyttet til onCompleted blir aldri kalt. Du kan se gjennom Rxjs-kontrakten for observabler her (http://reactivex.io/documentation/contract.html) :
En Observable kan lage null eller flere OnNext-varsler, som hver representerer ett enkelt utgitt element, og den kan deretter følge disse utslippsvarslingene med enten et OnCompleted- eller et OnError-varsel, men ikke begge. Etter å ha sendt et OnCompleted- eller OnError-varsel, kan den deretter ikke sende noen flere varsler.
For feilbehandling kan du se på: https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/errors.md
Svar #2
En annen og sannsynligvis den enkleste løsningen kan være å bruke add()-funksjonen.
Utsagnet vil alltid bli utført uavhengig av om en feil oppstod eller ikke (som finally-utsagnet i de fleste programmeringsspråk).
observer.subscribe(
function(x) { console.log('succeeded with ' + x ) },
function(x) { console.log('errored with ' + x ) },
function() { console.log('completed') }
)
.add(() => {
console.log("Will be executed on both success or error of the previous subscription")
);
Svar #3
Mens jeg hadde det samme spørsmålet, støtte jeg på denne GitHub-issuen.
Tilsynelatende må finally-metoden til Observable-objektet brukes i dette tilfellet.
Siterer fra Aleksandr-Leotech fra den tråden:
Complete og finally er helt forskjellige ting. Complete betyr at den observerbare steam var vellykket fullført. Fordi du kan ha mange suksesskall. Finally betyr at steam har avsluttet, enten vellykket eller ikke.
Det er ikke åpenbart med HTTP-forespørsler, men forestill deg to tilleggs-scenarier.
Musehendelser. Du vil motta en uendelig strøm av suksess-tilbakekallinger, men du vil aldri motta finally eller complete, fordi brukerhendelser aldri vil stoppe (med mindre du utløser en unntak med buggy kode, da vil du få error og finally).
Arbeider med web sockets. Du vil få flere suksess-callbacks, men på et tidspunkt vil kommunikasjonen din med back-end stoppe og du vil få både complete og finally med mindre du har noen feil, som vil kalle error og finally.
Så, du kan få flere eller ingen suksesskall, null eller ett feilkall, null eller ett komplett og null eller ett til slutt.
Svar #4
For å kjøre en tilbakeringing når observable fullfører eller feiler, bør du bruke finalize.
Eks :
this.service.yourObservable
.pipe(
finalize(() => {
// * This will always run when observable finishes the stream
console.log("Finally!");
// * callback for finally
})
).subscribe(
{
next: () => { // * Callback for success },
error: () => { // * Callback for error },
complete: () => {// * This gets called only on success }
})
