简体   繁体   中英

map is not a function rxjs angular

I'm new to RXJS and I'm struggling a bit to get the following code to work. In angular I'm doing a call to a REST API and the rest API returns an array. I only need certain data from the API in my model. I'm trying to do this with RXJS (so no forEach, ...) and this is what I have so far:

import { Injectable, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { DataPackage } from './models/data-package';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class PackageService implements OnInit{

  constructor(private http: HttpClient) { }

  getPackages(): Observable<DataPackage> {
    return this.http
    .get<any>('http://dummy.restapiexample.com/api/v1/employees')
    .pipe(
      map((data: any[]) =>
        data.map(
          (response: any) =>
            new DataPackage(response.employee_name, response.employee_salary, response.employee_age, new Date())
        )
      )
    );
  }

  ngOnInit() {      

  }
}

I'm getting the following error

ERROR TypeError: "data.map is not a function"
    getPackages package.service.ts:19

Your mock API is returning a response in this structure:

{
  "status": "success",
  "data": [
    { /.../ }
  ]
}

So you are trying to call .map on this object. Instead you want to navigate to the data property. There are a couple of ways of doing this, but I'll keep it simple.

getPackages(): Observable<DataPackage[]> {
  return this.http
    .get<any>('http://dummy.restapiexample.com/api/v1/employees')
    .pipe(
      map((response: any) => response.data // <--- navigate to "data"
        .map((item: any) => this.mapResponseItem(item))            
    );
}

private mapResponseItem(item): DataPackage {
  return new DataPackage(response.employee_name, 
    response.employee_salary, response.employee_age, new Date());
}

Edit: I moved the inner map out of the subscribe to hopefully make the .data navigation I added a little clearer. Also, you should be returning an array of DataPackage from getPackages .

Alternative

You can use the pluck operator in the pipe so ensure an array comes into your map RxJS operator.

getPackages(): Observable<DataPackage[]> {
  return this.http
    .get<any>('http://dummy.restapiexample.com/api/v1/employees')
    .pipe(
      pluck('data'), // <-- pass "data" on to map
      map((data: any) => data.map(item => this.mapResponseItem(item))            
    );
}

private mapResponseItem(item): DataPackage {
  return new DataPackage(response.employee_name, 
    response.employee_salary, response.employee_age, new Date());
}

Whichever approach you use is just a matter of taste. Neither method is typesafe as you're dealing with external data coming in to your system.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM