thecrusader
thecrusader

Reputation: 311

How to use ForkJoin for sequence of http requests Angular 4

I have a function which makes two http calls, the input of second http depends first http response and I need the two results to be returned at the same time. I have the below code which throws the error

SomeMethod(): Observable<any> {
    let firstResult;
    let secondResult;

    firstResult = http.get('////').map(data => {
        console.log('first response')
     secondResult = http.get('//// + {data.UserId}').map(response => {

        console.log('second response')
     })
    })

    return forkJoin([firstResult, secondResult]);
}

CallingMethod() {
    this.SomeMethod.subscribe(([firstResult, secondResult]) =>{
     /// Some logic
    })}

Getting error as undefined. Expected a observable, promise or array. After debugging got to know that first console output is printing, the second http call is never made and response is never seen.

How to return two nested calls responses together using forkJoin or any other mechanism?

Upvotes: 2

Views: 7773

Answers (4)

Ian Jamieson
Ian Jamieson

Reputation: 4816

Here is a StackBlitz of how to do this using concatMap. concatMap will execute sequentially, where as forkJoin will execute in parallel.

What you need to know

    const requests = [
      this.http.get('https://jsonplaceholder.typicode.com/todos/1'),
      this.http.get('https://jsonplaceholder.typicode.com/todos/2'),
      this.http.get('https://jsonplaceholder.typicode.com/todos/3'),
      this.http.get('https://jsonplaceholder.typicode.com/todos/4'),
      this.http.get('https://jsonplaceholder.typicode.com/todos/5'),
      this.http.get('https://jsonplaceholder.typicode.com/todos/6')
    ];


    from(requests).pipe(    
      concatMap((request) => request.pipe(delay(2200)))
    ).subscribe((res) => {
      this.results$.next(this.results$.getValue().concat(res))
    })
  1. We create an array of requests (which are observables).
  2. Use the from operator to take your array and emit each array item
  3. Flatten those emissions with concatMap

I added a delay here as well to simulate slow loading.

Upvotes: 6

Mjstk
Mjstk

Reputation: 508

Use Async & await to control multiple http requests.

async SomeMethod(): Promise <any> {

    let firstResult;
    let secondResult;
    firstResult = await http.get('////').toPromise();
    secondResult = await http.get('//// + {res1.UserId}').toPromise();

    return forkJoin(firstResult, secondResult);
}

 CallingMethod() {
    this.SomeMethod().then(result => {
       /// Some logic
    });
 }

Upvotes: 3

Phix
Phix

Reputation: 9880

forkJoin takes arguments inline, not as an array (unless that's a change in rxjs between latest and what was bundled in Angular v4)

const req1 = this.http.get('https://jsonplaceholder.typicode.com/todos/1');
const req2 = this.http.get('https://jsonplaceholder.typicode.com/todos/2');

const results = forkJoin(req1, req2)

Output:

[
  {
    "userId": 1,
    "id": 1,
    "title": "delectus aut autem",
    "completed": false
  },
  {
    "userId": 1,
    "id": 2,
    "title": "quis ut nam facilis et officia qui",
    "completed": false
  }
]

StackBlitz is in v6 but its easy enough to back track if needed.

Upvotes: 0

Xinan
Xinan

Reputation: 3162

The following code should work:

SomeMethod(): Observable < any > {
  let firstResult;
  let secondResult;

  return http.get('////').pipe(
    switchMap(res1 => http.get('//// + {res1.UserId}').pipe(
      map(res2 => [res1, res2])
    ))
  );
}

CallingMethod() {
  this.SomeMethod().subscribe(([firstResult, secondResult]) => {
    /// Some logic
  })
}

Upvotes: 1

Related Questions