Reputation: 499
I dont know where / how at all to catch http-errors when i repeatedly call an api?
I've been playing around with loading mock images from lorempicsum and of course i'd like to catch http-errors.
I've tried rxjs catchError() inside the method where i make my calls, but then i had to return an of(EMPTY) and it lead me nowhere. Then i realized, that i dont know where is should catch the http-errors, when i am using a pipe operator. Is that even possible? I mean like, if one of five calls fail, catch the error, do something and subscribe to the successful results?
In the end, i would like to display a grey box for every failing call, but i dont know how to get there from here...
Thx
Here is my image service
@Injectable()
export class MockImageService {
constructor(private httpClient: HttpClient, private readonly sanitizer: DomSanitizer) {}
getRandomImageBlobs(
numberOfImages: number,
widthInPx: number,
heightInPx: number
): Observable<Blob> {
return this.httpClient
.get(`https://picsum.photos/${widthInPx}/${heightInPx}/?random`, {
headers: { 'Content-Type': 'image/jpg' },
responseType: 'blob'
})
.pipe(repeat(numberOfImages));
}
getSafeURL(blob: Blob): SafeUrl {
const objectURL = window.URL.createObjectURL(blob);
const sanitizedObjectURL = this.sanitizer.sanitize(SecurityContext.URL, objectURL);
return this.sanitizer.bypassSecurityTrustUrl(objectURL);
}
}
my component that uses it
import { Component, OnInit, Input } from '@angular/core';
import { MockImageService } from '../../services/mock-image.service';
import { SafeUrl } from '@angular/platform-browser';
@Component({
selector: 'app-random-image-display',
template: `
<div class="container" fxLayout="row wrap" fxLayoutAlign="center" fxLayoutGap="4px">
<div *ngFor="let url of safeURLs">
<img [src]="url"/>
</div>
</div>
`,
styles: []
})
export class RandomImagesComponent implements OnInit {
@Input() numberOfImages: number;
@Input() widthInPx: number;
@Input() heightInPx: number;
public safeURLs: SafeUrl[] = [];
constructor(private imgService: MockImageService) {}
ngOnInit() {
// TODO catch invalid formats / http errors!
this.imgService
.getRandomImageBlobs(this.numberOfImages, this.widthInPx, this.heightInPx)
.subscribe((blob: Blob) => {
this.safeURLs.push(this.imgService.getSafeURL(blob));
});
}
}
and part of the containing components html
<app-random-image-display
[numberOfImages]="5"
[widthInPx]="200"
[heightInPx]="300"
></app-random-image-display>
Upvotes: 0
Views: 62
Reputation: 2751
I would suggest you create a more centralized error handling mechanism. This can be achieved by an HttpInterceptor. Any HTTP error will trigger the catchError
method as seen below
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, throwError as observableThrowError } from 'rxjs';
import { catchError } from 'rxjs/operators';
@Injectable()
export class MyHttpInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
catchError((err: any, caught: Observable<any>) => {
// Handle the error here
return observableThrowError(err);
}));
}
}
Register the Interceptor on the AppModule or CoreModule
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { NgModule } from '@angular/core';
@NgModule({
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: MyHttpInterceptor,
multi: true }
]
})
export class CoreModule {
// rest of code
}
Upvotes: 1
Reputation:
I believe you'll want to add another callback method inside of the subscribe for getRandomImageBlobs.
.getRandomImageBlobs(this.numberOfImages, this.widthInPx, this.heightInPx)
.subscribe((blob: Blob) => {
this.safeURLs.push(this.imgService.getSafeURL(blob));
}, (error: any) => {
// handle error
});
Upvotes: 0