RxJs Observable - Handle 404 by emitting default value

John Dibling

I am calling MS Graph to get a user's photo:

    // lets get the photo itself
    let photo$ = this.graph.get$(`users/${id}/photo/$value`, ResponseContentType.Blob)
        .map(resp => {
            return new Blob([resp.blob()], { type: resp.headers.get['Content-Type']}); })
        .map(photo => {
            let urlCreator = window.URL;
            return this.sanitizer
                .bypassSecurityTrustUrl(urlCreator.createObjectURL(photo));
        })
        .catch(function (e) {
            if(e.status === 404) {
                // no photo for this user!
                console.log(`No photo for user ${id}!  Returning default...`);
                return undefined;
            }
        })
        .toPromise();

However many users don't have a photo. In that case what I would like to do is create an object URL for some default photo (one of these perhaps) and emit that from the Observable. Or even just emit an undefined from the Observable, which I can handle in the front end by displaying some default image.

I know that my catch is firing, because I see this in the browser console:

No photo for user xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx! Returning default... (output redacted)

I'm actually pulling in many different bits of data for each user, each in its own Observable. I then convert each of those Observable to Promises, and then do a Promise.all() on all of them.

    // let's pull all of this together to form a ConcreteUser
    return Promise.all([photo$, ...])
        .then(values => {
            const photo = values[0];
            ...

The problem is in the case of a 404 for a user's photo, the whole Promise.all aborts, and I can't retrieve the user.

I've tried catching errors in the photo$ observable and emitting an undefined (which I planned to handle later), but it doesn't seem to be doing what I want.

How do I handle 404s in my Observable here, and emit something else (perhaps undefined) instead of killing the observable?

John Dibling

I think I may have figured this out. A hint was lurking in the browser console...

TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

Reading the RxJs documentation on error handling showed them doing what I'm trying to do, so I was a bit confused by this. But then I noticed that in the documentation they call a mystery function getCachedVersion() which I assumed returned an actual cached thing. However if they instead returned an Observable.of() some actual cached thing, then that might explain it.

When I changed my catch code to:

        .catch(function (e) {
            if(e.status === 404) {
                // no photo for this user!
                console.log(`No photo for user ${id}!  Returning default...`);
                return Observable.of(undefined);
            }
        })

...it all started working.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

RxJS - Observable is not emitting value with .next() on first call

RxJS - switchMap not emitting value if the input observable is empty array

Observable only emitting first value

RxJS: Setting default value for observable from another observable

Rxjs: Observable with takeUntil(timer) keeps emitting after the timer has ticked

Setting visibility of ProgressBar before and after emitting value from an observable

How to handle request on interceptor after getting the value from an observable on rxjs and angular?

rxjs Observable: handle unsubscribe of all subscribe

How to handle an rxjs observable response that could be empty?

RxJS forkJoin not emitting values

RxJs get value from observable

Rxjs combinelatest observable value is undefined

Rxjs: shorthand of create observable from value or observable

Identify emitting observable in RxJava

Observable not emitting any values

Emit Observable value and handle it in component

Observable that behaves as BehaviorSubject(observable with default value)

rxjs pairwise is emitting duplicate values

How to delay sequence emitting in Rxjs

Rxjs Subject not emitting data immediately

Return a default value with scan Observable

RxJava : observable emitting duplicate values

Return observable before emitting event

Rxjs assign value in observable to global variable

How to skip first value of an observable with RxJS?

How to get current value of RxJS Subject or Observable?

Rxjs: Execute code and emit value on completion of Observable

RXJS: Return the manipulated value of outer observable

Problem returning value from RxJS Observable