Search code examples
angular6angular-httpclientrxjs6

HttpClient GET transform response array of Objects


Following is my model.

export interface AuditTrail {
    logAction:string,
    targetEmpId:string,
    createdDate:Date
}

Code below retrieves data from a GET call and transforms it.

  public getAuditTrails() {
   return this.http.get<AuditTrail[]>(this.auditTrailUrl)
    .pipe(
      map((data :Object[]) =>  {
        return data.map(value => {
          const auditTrail:AuditTrail = {
            logAction:value["logAction"],
            targetEmpId:value["targetEmpId"]["empCode"],
            createdDate:value["loggedDateTime"]
          }
          return auditTrail;
        });
    })
    )
  }

This code works alright. However my question is how can I avoid the array iteration data.map(value => {and use rxjs operators for the same.

The question is intended to improve my understanding of rxjs operators hence the solution should use rxjs operators.


Solution

  • It depends on what you want to final return value to be, i.e., a stream of AuditTrail objects or a single AuditTrail[] array.

    Stream:

    public getAuditTrails(): Observable<AuditTrail> {
     return this.http.get<SomeObject[]>(this.auditTrailUrl).pipe(
       flatMap(data => data),
       map<SomeObject, AuditTrail>(value => ({
         logAction:value["logAction"],
         targetEmpId:value["targetEmpId"]["empCode"],
         createdDate:value["loggedDateTime"]
       })
     );
    }
    

    Above, flatMap is taking the source array and emitting each value as an item in a new observable stream allowing each individual item to be passed to a subsequent map.

    Array:

    If you want this to be reduced to an array, you can pipe toArray:

    public getAuditTrails(): Observable<AuditTrail> {
     return this.http.get<AuditTrail[]>(this.auditTrailUrl).pipe(
       flatMap(data => data),
       map<SomeObject, AuditTrail>(value => ({
         logAction:value["logAction"],
         targetEmpId:value["targetEmpId"]["empCode"],
         createdDate:value["loggedDateTime"]
       }),
       toArray()
     );
    }
    

    Personally, I don't think there's any advantage to flat mapping and using map(data = data.map(...)) is fine.