-1

I have the following components in an Angular site:

product-api.service.ts:

export class ProductApiService {

  constructor(private api: ApiHandlerService) { }

  getProductsFromAPI() : Observable<Product[]> {
    return this.api.get<Product[]>("/api/products");
  }

}

product.service.ts:

export class ProductService {

  constructor(private productApiSvc: ProductApiService) {}

  getProducts() : Product[] {
    this.productSvc.getProductsFromAPI().subscribe(
      result => {
        // return list here
      }
    )
  }

}

product-list.component.ts

products: Product[];

constructor(private productSvc: ProductService) { }
  
ngOnInit(): void {
   this.products = this.productSvc.getProducts();
}

My component class is using product.service class's getProducts() method to get list of products. The problem is getProducts returns Observable<Product[]>. How can I convert this to return Product[]? Is it better to remove product.service.ts wrapper and call getProductsFromAPI directly from list.component.ts class? If so, what are the benefits of it? Thanks!

Steve Holgado
  • 11,508
  • 3
  • 24
  • 32
developer
  • 1,401
  • 4
  • 28
  • 73
  • 4
    *"...`getProducts` [I think you meant `getProductsFromAPI`] returns `Observable`. How can I convert this to return `Product[]`?"* I don't think you can (synchronously). You could convert it to `Promise`, but only over a specific period of time, righ? Since an observable produces values over a period of time. See [the documentation](https://angular.io/guide/observables). You probably don't want to actually do what you think you want to do. – T.J. Crowder Jul 13 '21 at 15:26
  • 1
    https://stackoverflow.com/q/14220321/3001761, basically – jonrsharpe Jul 13 '21 at 15:27
  • Got it so it should not convert Observable to Product[]. – developer Jul 13 '21 at 15:35

1 Answers1

2

I wouldn't think that the product.service.ts wrapper would be necessary.

Here is the common pattern for handling an http response in a component.

export class ProductListComponent implements OnInit, OnDestroy {
  products: Product[] = [];
  sub!: Subscription;
  constructor(private productService: ProductApiService) { }

  ngOnInit(): void {
    this.sub = this.productService.getProducts().subscribe(
       products => this.products = products
    );
  }
  ngOnDestroy(): void {
    this.sub.unsubscribe();
  }
}

From the point of view of the client-side application, an HTTP request is asynchronous. That means that the http request is submitted, the code continues, and at some later point in time, the code is notified that the response was returned. This means that you can't have a simple function call (like in your ProductService getProducts() method) return the resulting data.

Instead, you subscribe in the component and when the data is returned, it updates a local variable (this.products in the above example). If the UI is bound to products, change detection will pick up the changed products variable and the returned products will appear.

<OMG they are FAST with getting rid of that "h_pe th_s h_lps". Someone must have a script to strip these as fast as they are posted!>

For more information, check this out: https://www.youtube.com/watch?v=knUgpZrxUII

DeborahK
  • 57,520
  • 12
  • 104
  • 129
  • Thanks Deborah, it makes sense now. How wonderful it is that I had started learning Angular with your Pluralsight videos 3 years back and you are still helping :) – developer Jul 14 '21 at 10:46