I have implemented some error handling code in my main
function as below. It uses the catch
operator to filter and report on errors in one stream and ignore them in another. This allows me to know about and report on errors that occur with requests whilst not failing the entire stream so that subsequent requests can continue.
For reasons that might not be apparent in the code snippets below I am impementing a custom driver to request and handle data. I'm not using the cycle http driver.
Here's my code that successfully reports an error:
function main(sources) {
// Catch driver errors so they can be logged
const error$ = sources.CustomDriver
.map(x => x.catch(e => Rx.Observable.just(e)))
.flatMap(p => p)
// Filter out the errors to deal with requests that did not fail
const data$ = sources.CustomDriver
.map(x => x.catch(e => Rx.Observable.empty()))
.flatMap(p => p)
return {
CustomDriver: Rx.Observable.just('initial event'),
Log: data$,
Error: error$
}
}
Cycle.run(main, {
CustomDriver: makeCustomDriver(),
Log: msg$ => { msg$.subscribe(
msg => console.log('LOG: ', msg),
err => console.log('problem with Log driver: ', err),
() => console.log('Log Completed')
) },
Error: msg$ => { msg$.subscribe(
e => console.log('ERR: ', e),
err => console.log('problem with Error driver:', err),
() => console.log('Error Completed')
) }
})
function makeCustomDriver() {
return function customDriver(requests$) {
return requests$
.map(request => Rx.Observable.fromPromise(makeFailedRequest()))
}
}
function makeFailedRequest() {
console.log('some API request')
return Promise.reject('error')
}
The output is as follows:
some API request
some API request
Log Completed
ERR: error
Error Completed
On the plus side the error is reported. However, the API request is actually made twice, which is not what I expected to happen initially.
After learning some more RxJS and getting a better understanding of Hot and Cold observables I realised that I was creating two subscriptions to the CustomDriver stream (one for error$ and one for data$) and because the CustomDriver Observable was cold it would repeat the Observable.just
for each subscriber.
So I tried to make my CustomDriver Observavble hot with share
:
function makeCustomDriver() {
return function customDriver(requests$) {
return requests$
.map(request => Rx.Observable.fromPromise(makeFailedRequest()))
.share()
}
}
With that change, the output is as follows:
some API request
Error Completed
Log Completed
So I managed to get rid of the duplicate request but the error was swallowed up in the process.
What is happening with share
that causes the errors to be lost and how can I avoid duplicate requests without losing errors?