How to catch only specific type of exception without abort the sequence

2.4k views Asked by At

RxJs does not seem to have a variation of catch() method which allow to capture only certain type of exception. But many times I found myself in a situation where such operator is needed.

For example, imaging I need to parse each line of a log file and print the parsed message. Some lines of the log file might have been corrupted, but I really don't care and just want to output a "Log message corrupted" for such line and continue to the next line.

If catch() did allow us to specify a specific type of error to catch and pass through all other errors, we can then do some thing like pseudo-code below

readLogs()
.flatMap parseLog
.catchOnly ParseError, () ->
  'Log message corrupted'
.subscribe (logMessage) ->
  console.log logMessage

I was wondering what would be the proper way of RxJs to do that given the current limitation of catach().

3

There are 3 answers

2
paulpdaniels On BEST ANSWER

You would need to nest catch in order to prevent an error from terminating the entire chain and you would need to separate the logic for splitting and parsing lines:

import {of, throwError} from 'rxjs'
import {flatMap, map, catchError} from 'rxjs/operators'



function handleErrors(e) {
    return (e instanceof ParseError) ? 
            of("Log message corrupted") : throwError(e);
}

readLogs().pipe(
  flatMap(splitLines)
  flatMap(line => 
    of(line).pipe(
      map(parseLine), 
      catch(handleErrors)
    )
  )
)
.subscribe(
  parsedLine => console.log(parsedLine),
  e => console.error('Fatal error: ' + e);
);
0
user3302319 On

The catch/catchOnly operation is limited in what it can do.

There is no way for a lower link in an Observable chain to tell a higher link to ignore an error. After flatMap parseLog delivers the error, it is done and there is no mechanism for catchOnly to tell it to backtrack and ignore that error.

That means the catchOnly operation can at best restart the sequence when it sees a particular error.

To achieve the effect you're looking for and keep the sequence going, flatMap parseLog should avoid producing the error condition in the first place. So parseLog would need a wrapper to catch the ParseError exception and convert it into a valid logMessage.

1
Adam Kettani On
        .catch(error => {
            if (whatever) {
                console.log('I handle this in a cool way')
                return Observable.empty(); // Or an observable that emits whatever you want
            } else {
                return Observable.throw(error);
            }