Solution - Retry Operator
Solution
import { fromEvent, throwError } from 'rxjs';
import { ajax } from 'rxjs/ajax';
import { catchError, finalize, map, mergeMap, retry } from 'rxjs/operators';
/** The UserResponse represents the shape of the response from the API. */
interface UserResponse {
data: {
id: number;
email: string;
first_name: string;
last_name: string;
avatar: string;
};
}
/** The random function returns a random integer inclusively between `min` and `max`. */
function random(max: number, min: number): number {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
const output = document.getElementById('output') as HTMLTextAreaElement;
const btn = document.getElementById('btn') as HTMLButtonElement;
fromEvent(btn, 'click')
.pipe(
map(() => random(10, 15)),
mergeMap((id) =>
ajax.getJSON<UserResponse>(`https://reqres.in/api/users/${id}`).pipe(
map((response) => response.data),
catchError((error) => {
output.value += `\n\n${error.message}`;
output.scrollTop = output.scrollHeight;
return throwError(error);
})
)
),
retry(4),
finalize(() => {
btn.classList.add('cursor-not-allowed');
btn.classList.add('opacity-50');
})
)
.subscribe({
error: (e) => console.error('observer', e),
next: (value) => {
output.value += `\n\n${JSON.stringify(value, null, 2)}`;
output.scrollTop = output.scrollHeight;
},
complete: () => console.log('complete')
});
This was a fun exercise where we are bringing together multiple operators for error handling.
Let's review the code above:
- First, we use the
fromEvent()
operator to add an event listener to thebtn
element'sclick
event. - We then
map()
theMouseEvent
to a random integer between10
and15
. - Using the
mergeMap()
operator we merge the output of theajax.getJSON()
Observable. When we have successfully fetched a user we use themap()
operator to return the nesteddata
property from theresponse
object. - When an error occurs with the network request the
catchError()
operator receives theerror
. We update theoutput
textareavalue
property with the error message, scroll the textarea to the bottom, and return a new Observable created by thethrowError()
operator with theerror
value. - When an error notification occurs the
retry()
operator will prevent the error from being emitted to the Observer and completing the Observable. The use ofretry(4)
with thecount
argument set to4
will allow for the click event Observable to retry four additional times. Once thecount
is decremented to-1
the error is emitted to the Observer. - Finally, we use the
finalize()
operator to disable thebtn
element.