0

I have a service that is to chain a set of http requests and return a list of products. This is what I have so far:

listForDisplay(categoryId: string): Observable<any[]> {
    if (!categoryId) return of([]);
    return this.listFields(categoryId);
}

private listFields(categoryId: string): Observable<any[]> {
    return this.fieldService.list(categoryId, true).pipe(
        flatMap((fields: Field[]) => {
            if (!fields) return of([]);
            return this.listProducts(categoryId, fields);
        }),
    );
}

private listProducts(categoryId: string, fields: Field[]): Observable<any[]> {
    return this.productService.listSpecificationProducts(categoryId).pipe(
        flatMap((products: any[]) => {
            if (!products) return of([]);
            return this.mapVisibleFields(fields, products);
        }),
    );
}

private mapVisibleFields(fields: Field[], products: any[]): any[] {
    console.log(products);
    return this.productModelService.mapProductsWithSpecificationFields(fields, products);
}

In my controller I call this:

private getCategory() {
    this.selectorSubscription = this.selectorService.category.subscribe(categoryId => {
        this.products = [];
        this.specificationService.listForDisplay(categoryId).subscribe((products: any[]) => {
            console.log(products);
            this.products = products;
        });
    });
}

The problem is that the console.log in the first part returns an array. The console.log in the controller only returns a single item....

Like this:

enter image description here

I am clearly doing something wrong. Can anyone help?

r3plica
  • 13,017
  • 23
  • 128
  • 290

1 Answers1

0

As per rxjs documentation, flatMap

Projects each source value to an Observable which is merged in the output Observable.

This is why your subscribe is being called multiple times with each value coming one at a time. Are you sure you need flatMap? It seems from what you are trying to do, map would is more appropriate.

Shahzad
  • 2,033
  • 1
  • 16
  • 23
  • I don't see why it wouldn't work. What happened when you tried it? – Shahzad Dec 30 '19 at 19:12
  • Type 'Observable>' is not assignable to type 'Observable'. Type 'any[] | Observable' is not assignable to type 'any[]'. Type 'Observable' is not assignable to type 'any[]'. – r3plica Dec 30 '19 at 19:18
  • this post https://stackoverflow.com/questions/37771855/chaining-observables-in-rxjs says flatMap is like promise.then, which is what I am trying to do. I want the last value from all the chains – r3plica Dec 30 '19 at 19:20
  • The typing issue is because you are returning different types from the same function. For example, return of([]) gives Observable, but mapVisibileFields returns just any[]; I suggest change the return types to just `any` for the time being and see if map works. – Shahzad Dec 30 '19 at 19:25
  • `map` is also like a promise.then. `flatMap` just flattens your array and converts all the items into multiple observables. You don't need everything to be a separate observable, you just want the final list of products, which is what map will give you – Shahzad Dec 30 '19 at 19:27
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/205100/discussion-between-shahzad-b-and-r3plica). – Shahzad Dec 30 '19 at 19:27