简体   繁体   中英

Subscription to Observable

I have an Angular app where I retrieve data from API using HttpClient.

I would like to get raw data from API and sent them to corresponding service. The services has methods that map raw data to model objects and return them to the component.

The problem is, I get the data from API (return Observable), I subscribe in the service method and then I do not know how to pass data to the component.

Api service where I retrieve data from API. Then I send raw data and Hotel service where I want to map raw data to model and send to the component

@Injectable()
export class ApiService {
  ...
  public getHotelById(hotelId: number): Observable<any> {
      return this.http
          .get(API_URL + '/hotel/' + hotelId)
          .map((response) => {
              return response;
          })
  }
  ...
}


@Injectable()
export class HotelService {
  ...
  public getHotelById(id: number): Subscription {
    return this.api.getHotelById(id).subscribe(
        (response) => {
            let hotel = new HotelModel(response.hotel);

            hotel.mapCountry(response.country);

            return hotel;
        }
    );
  }
  ...
}

Can anyone help me how to retrieve datafrom service in the component? Im getting error that object which hotelservice returns is subscription and I cannot subscribe to it.

Is there any way how to do this? I do not want to do some business logic in the API service. On that place I just want to retrieve data.

Component method

  ngOnInit() {
    this.activatedRoute.queryParamMap.subscribe(
        (map) => {
            this.hotelId = this.activatedRoute.snapshot.params['id'];

            this.hotel = this.hotelService.getHotelById(this.hotelId)
                .subscribe(
                (hotel) => {
                  this.hotel = hotel;
                }
            )
        }
    )
  }

map your response instead of subscribing to it. Subscriptions are the "end of the road", while mapping is just "changing lanes".

export class HotelService {
  ...
  public getHotelById(id: number) {
    return this.api.getHotelById(id).pipe(map(
        (response) => {
            let hotel = new HotelModel(response.hotel);

            hotel.mapCountry(response.country);

            return hotel;
        }
    ));
  }
  ...
}

I think a good way for you is to map your result in the specific function "getHotelById" (You make an ORM like)

@Injectable()
export class ApiService {
  ...
  public getHotelById(hotelId: number): Observable<any> {
      return this.http
          .get(API_URL + '/hotel/' + hotelId)
          .map((response) => {
            let hotel = new HotelModel(response.hotel);

            hotel.mapCountry(response.country);

            return hotel;
          })
  }
  ...
}


@Injectable()
export class HotelService {
  ...
  public getHotelById(id: number): Observable<any> {
    return this.api.getHotelById(id);
  }
  ...
}

And in your component nothing change.

Do you really need two services?

@Injectable()
export class HotelService extends AbstractHttpService {

  constructor (
    private httpClient: HttpClient,
  ) {
    super();
  }

  loadHotels(): Observable<Hotel[]> {
    const url = this.url('hotels');

    return this.httpClient.get<Hotel[]>(url, this.standardHttpOptions);
  }
}

The abstract class has some helpers for querying the target URL and provides standard http options for the get call.

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