amad-person
amad-person

Reputation: 501

How to store HTTPErrorResponse objects from multiple HTTP requests in an array?

I'm trying to build an API validator in my Angular application. I have a list of URLs that I need to GET or POST, and store any HTTP errors in an array which will then be displayed in the UI.

I have implemented the following service to do this:

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { DataSource, ConfigValidationErrorObject } from './customTypes';

@Injectable()
export class ApiValidationService {
  apiValidationErrors: Array<ConfigValidationErrorObject> = new Array<ConfigValidationErrorObject>();

  constructor(
    private _httpClient: HttpClient,
  ) { }

  validate(dataSourceArray: Array<DataSource>): Array<ConfigValidationErrorObject> {
    dataSourceArray.map((url) => { this.validateApi(dataSource) });

    return this.apiValidationErrors;
  }

  validateApi(dataSource: DataSource) {
    if (dataSource.httpRequestType === 'GET') {
      this.executeGetRequest(dataSource.url, dataSource.options).subscribe(
        (data) => console.log(data),
        (error: HttpErrorResponse) => {
          this.addApiValidationError(error);
        }
      );
    }

    if (dataSource.httpRequestType === 'POST') {
      this.executePostRequest(dataSource.url, dataSource.body, dataSource.options).subscribe(
        (data) => console.log(data),
        (error: HttpErrorResponse) => {
          this.addApiValidationError(error);
        }
      );
    }
  }

  executeGetRequest(url: string, options: any) {
    return this._httpClient.get(url);
  }

  executePostRequest(url: string, body: any, options: any) {
    return this._httpClient.post(url, body, options);
  }

  addApiValidationError(httpErrorResponse: HttpErrorResponse) {
    const apiValidationError: ConfigValidationErrorObject = {
      message: httpErrorResponse.message,
    };

    this.apiValidationErrors.push(apiValidationError);
  }
}

When I use the validate() method in my component, I want the array it returns to be populated with my custom error objects. But I get an empty array back, even when errors are being thrown (they are being logged to the console correctly). I expect it's because of asynchronous HTTP requests.

I'm reading up on Observables, but I'm not sure if I can use them because I need the error objects and not the data returned from the HTTP requests. I want to know if I need to use Observables or if I should be looking at Promises? If I need to use Observables, could anyone please help me get started with it for my problem.

I'm pretty new to Angular, so I'm having trouble deciding how to solve this issue. Any suggestions would be appreciated.

Upvotes: 0

Views: 205

Answers (1)

user4676340
user4676340

Reputation:

I would go like this

forkJoin(
  getCallOne()
    .pipe(map(() => null), catchError(error => {/* what you want to do here */})),
  getCallTwo()
    .pipe(map(() => null), catchError(error => {/* what you want to do here */})),
  postCallOne()
    .pipe(map(() => null), catchError(error => {/* what you want to do here */})),
  PostCallTwo()
    .pipe(map(() => null), catchError(error => {/* what you want to do here */})),
).pipe(
  map(errors => errors.filter(error => !!error))
)

You can then either subscribe to it, or use the async pipe in your template

  • forkJoin creates an array of observables and emits only when all calls are completed
  • map the answers to null because you won't use it (apparently)
  • use catchError to catch the error and return it as a valid observable
  • map the final errors to filter only the errors (removing the null values of valid calls)

Upvotes: 2

Related Questions