2015-05-22 25 views
6

jestem stara się obsłużyć błędy z Rx w sposób spodziewałem.RxJS - Catch i prowadzić

Kiedy mają widoczny (na przykład ze strumienia click) i wystąpi wyjątek chcę go złapać, ale prowadzić. Wszystkie rozwiązania, które próbowałem złapać błąd, a następnie zakończyć obserwowalne. Czy istnieje sposób na złapanie i kontynuowanie?

Jako przykład, poniżej Obserwowalne emituje „1”, a następnie „Error”, a nie „3”.

var range = Rx.Observable.range(1,3) 
    .map(function(i){ 
     if(i === 2){ 
     throw "Error"; 
     } else { 
     return i; 
     } 
    }) 
    .catch(function(e){ 
     return Rx.Observable.return(e) 
    }); 

range.subscribe(function(i){ 
    console.log(i) 
}); 
+0

Jedynym sposobem na kontynuację sekwencji źródłowej nie jest rzucanie. Czy możesz nam powiedzieć, jaki jest twój prawdziwy przypadek użycia? –

+0

Obserwowalna umowa polega na tym, że musi ona wyemitować dla obserwatora wzór: (OnNext) * (OnCompleted | OnError). Tak więc, gdy sekwencja emituje OnError, kończy się. –

+0

@OliverWeichhold prawdziwym przypadkiem jest obserwowalne zdarzenie click, które można zaobserwować w postaci 'flatMap()' na żądanie http. Jeśli/kiedy żądanie http nie powiedzie się, obserwowalne kliknięcie przestaje emitować. – MaxWillmo

Odpowiedz

9

Podczas gdy spodziewane zachowanie nie może być osiągnięta ze względu na obserwowalnych umowy (OnNext)* (OnCompleted|OnError), istnieją praktyczne sposoby wokół to właściwie działa poprzez wprowadzenie gorący widoczne.

let hotRange = Rx.Observable.range(1,3).publish(); 

let safeRange = hotRange 
    .map(function (i) { 
    if (i === 2) { 
     throw "Error"; 
    } else { 
     return i; 
    } 
    }) 
    .retry(); 

safeRange.subscribe(i => console.log(i)); 
hotRange.connect(); 

See the JSBin. Obwieszczenie, o którym wspomniałeś w pytaniu, jest zimne Obserwowalne. To behaves as a movie, więc jeśli błąd się dzieje, a my ponownie zarejestrować, musimy zapisać się od początku „Film”, czyli 1 następnie "Error".

Prawdopodobnie miałeś domyślne założenie, że Rx.Observable.range(1, 3) było Live Observable, tj. "Hot". Ponieważ nie jest, zrobiłem hotRange powyżej, używając publish(). W ten sposób będzie emitował swoje wydarzenia niezależnie od swoich subskrybentów. Jeśli chcemy mieć możliwość "kontynuacji" po błędzie, potrzebujemy naszego źródła ("hotRange") bez błędów. Dlatego range.map() nie jest gorący Obserwowalny. retry() będzie przechwytywać błędy na hotRange.map() i zastąpić je hotRange.map(). Ponieważ hotRange jest gorący, każdy wykonanie retry() będzie inny, ponieważ nie pamięta poprzednie wartości emitowanych przez hotRange. Więc gdy błąd spowodowany 2 zastępuje hotRange.map() w ponawiania, hotRange będzie następnie emitują 3 i przekazać funkcję mapa bez błędów.

+0

Ma to sens, jeśli wystąpi tylko jeden wyjątek. Praca w N-case 'Retry' prawdopodobnie byłaby lepsza zamiast' catch'. – paulpdaniels

+0

Dobra uwaga. Zaktualizowałem odpowiedź. Dzięki –

+0

@ AndréStaltz. Ale w metodzie subskrybowania obsługa błędów nie emitowała niczego. Jak możemy uzyskać błąd w procedurze obsługi błędów? – xgrommx