2

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?

4 Answers 4

6

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Do you have any suggestion how to modify your code, to get a result once (like forkJoin does) after all sequential(!) requests got completed?
Arg, could not edit anymore. If anyone else is searching for this behaviour, it´s just like this: from(requests).pipe( concatMap((request) => request.pipe(delay(2200))), reduce((acc, cur) => [...acc, cur], []), ).subscribe((res) => { console.log('res', res); })
@juli I think toArray() would also work instead of reduce
2

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
    });
 }

1 Comment

touché my friend
1

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
  })
}

2 Comments

i am getting the following error after using the code the this context of type void is not assignable to methods this of type observable even followed the link rxjs pipe but coudn't solve
You need to post your full code in order to get it properly debugged. I think it's just some silly tiny mistakes somewhere.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.