1

I'm trying to wrap my head around how to implement this. My first GET returns an array of objects like so:

{
  "stuff": [
    {
      "creationTime": 1502476634000,
      "id": 1
    }
    {
      "creationTime": 1502476634001,
      "id": 2
    }
    {
      "creationTime": 1502476634002,
      "id": 3
    }
  ]
}

For each object I need to make another GET with that objects id to another endpoint. What is the best way to call the 2nd GET? for each loop and keep calling GET with each id and pushing response to an array? I looked at some older stack overflow answers and they mentioned q.all() but that is deprecated.

yurzui
  • 205,937
  • 32
  • 433
  • 399
Anthony
  • 2,330
  • 8
  • 44
  • 64
  • 1
    A loop would be fine, fire off another get inside the loop for each item and in the `then` push the result to an array (if that is what you want to do). If you want a less chatty interface *and* you have source control over the server you could change it to take an array of ids and return an array of results. – Igor Aug 11 '17 at 20:51
  • 2
    Have you looked at e.g. https://stackoverflow.com/questions/41204055/rxjs-with-multiple-forkjoin-when-doing-http-requests? A quick search of the internet suggests plenty of material about doing parallel requests. – jonrsharpe Aug 11 '17 at 20:55

2 Answers2

1

From the HttpClient I'm assuming you're working with Angular4+.

SERVICE:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class MyService {

  constructor(private http: HttpClient) { }

  getArray() {
    return this.http.get('http://myapi/getarray');
  }

  getItemPassingId(id) {
    return this.http.get(`http://myapi/getItem/${id}`);
  }
}

COMPONENT:

import { Component, OnInit } from '@angular/core';
import { first, mergeMap } from 'rxjs/operators'; // import pipeable (formerly lettable) operators
import { forkJoin } from 'rxjs/observable/forkJoin';
@Component({
  selector: 'my-component',
  templateUrl: 'my-component.html'
})

export class MyComponent implements OnInit {
  constructor(private myService: MyService) { }

  ngOnInit() { }

  onAction() {
    this.myService.getArray() // get the array
      .pipe(
        first(),   // this would complete the observable on first value (no need to unsubscribe)
        mergeMap((array: Array<{creationTime: number, id: number}>) => {
          return forkJoin(array.map((item) => { // loop through the array and return the call based on each item's id
            return this.myService.getItemPassingId(item.id);
          }));
        })
      )
      .subscribe((results) => { // you'll get the finalized results here as an array
        console.log(results);
      });
  }
}

Hope this helps.

Muhammad Ahsan Ayaz
  • 1,867
  • 10
  • 12
0

Take a look at this link. I had the same problem and it resolved it for me:

http://blog.danieleghidoli.it/2016/10/22/http-rxjs-observables-angular

Here is some pseudo code, since you haven't provided much information:

return this.http.get('/api/getStuff').flatMap((stuff: any[]) => {
    if (stuff.length > 0) {
        return Observable.forkJoin(stuff.map((stuff: any) => {
            return this.http.get('/api/getAdditionalStuff' + stuff.id).map((res: any) => {
                // do what you need to do with additional stuff
                // in my case I added the additional stuff to a property of the 
                // original call
                stuff.additionalStuff = resp;
                return stuff;
            });
        }));
    }
    return Observable.of([]);
});
Oleksandr Pyrohov
  • 14,685
  • 6
  • 61
  • 90
DwankyDan
  • 39
  • 3