-
Notifications
You must be signed in to change notification settings - Fork 5
Error Handling
Due to the synchronous nature of iterables here, you can always resort to the regular try/catch
at the point where iteration
is triggered in your code. This however presents some problems:
- Reusable iterables can trigger different errors, depending on usage, which means manual error handling will be required at every point of triggering an iteration.
- Verbose error-handling coding around every use of iterables is a fairly poor and time-consuming practice.
That's why here we are covering error handling strictly during iteration, as values are retrieved one by one. This library supports explicit + implicit ways of handling iteration errors, as documented below.
You can handle all upstream iteration errors with a catchError operator at the end of the pipeline:
pipe(iterable, ...operators, catchError((error, ctx) => {
// Handling the error (logging it, etc)
// After that, you can any of the following:
//
// - re-throw the original error;
// - throw a new error;
// - do nothing (the value becomes simply skipped);
// - provide an alternative value, via ctx.emit(value)
}))
Parameters passed into the error handler:
-
error
- the original error that was thrown; -
ctx
- iteration error context - see IErrorContext type.
You can use catch
on any piped iterable:
pipe(iterable, ...operators)
.catch((error, ctx) => {
});
This will simply append catchError to the end of the pipeline, so the result is the same as with the explicit error handling. However, this adds the flexibility of handling errors separately from the pipeline implementation.
You can chain as many error handlers as you want, each handling what's upstream, after the last error handler.
For explicit error handling, this means you can have any number of catchError operators inside the pipeline:
pipe(iterable, operator1, catchError, operator2, operator3, catchError);
//=> first catchError will handle errors thrown by operator1
//=> second catchError will handle errors thrown by operator2 and operator3
//=> second catchError will handle all errors, if the first catchError re-throws
For implicit error handling, this means you can chain any number of catch
handlers at the end of the pipeline,
each will be appending another catchError to the end of the pipeline:
pipe(iterable, ...operators)
.catch() // first handler
.catch() // second handler
.catch() // third handler
// this will produce:
// pipe(iterable, ...operators, catchError, catchError, catchError);