1
votes

I created a Service in Angular2 which is responsible for making REST call to java services and get Array of products using HTTP Observable.

getAll(): Observable<Product[]>{
    let data$ = this.http
        .get(`${this.baseUrl}/productdata`, {headers: this.getHeaders()})
        .map(mapData)
        .catch(handleError);
    console.log(' object array:' , data$)
    return data$;
}

I have then written a subscriber for this Observable in my component and placed inside the ngOnInit() method and wanted to just extract the first product so placed inside ngOnInit().

this.product = this.products[0];

ngOnInit() {
 this.productService
        .getAll()
        .subscribe(
            /* happy path */ p => this.products = p,
            /* error path */ e => this.errorMessage = e,
            /* onComplete */ () => this.isLoading = false);
this.product = this.products[0];
}

But the last operation in OnInit method is causing product to be undefined because of the asynchronous behavior of Observable. Similarly, I am not able to use the property of product to interpolate in HTML component. I want the extraction to be automatic. So can you provide me a way to do that?

3

3 Answers

1
votes

You actually answered your own question - since it's asynchronous, your call to this.product = ... is called immediately, while the observable takes some time to return. Solution is simple:

ngOnInit() {
 this.productService
    .getAll()
    .subscribe(
        /* happy path */ p => {
            this.products = p;
            this.product = this.products[0];
        },
        /* error path */ e => this.errorMessage = e,
        /* onComplete */ () => this.isLoading = false);
}

Include the set inside of the observable callback.

0
votes

your code:

this.product = this.products[0];

is being executed before it is defined. Move it into your on success function

this.productService
    .getAll()
    .subscribe(
        /* happy path */ p => {
            this.products = p;
            this.product = this.products[0];
        },
        /* error path */ e => this.errorMessage = e,
        /* onComplete */ () => this.isLoading = false
);
0
votes

Since you are using observables, you can take advantage from all the methods of an observable such as the .map() function which you're already using.

this.productService
  .getAll()
  .map(products => products[0])
  .subscribe(
    /* happy path */ product => this.product = product,
    /* error path */ e => this.errorMessage = e,
    /* onComplete */ () => this.isLoading = false
  );