2

I am trying to call 3 different APIs before a component loads using the Resolve.

This code below is written inside the resolve function and is returning an object with all response packaged.

Now When The component loads, before I receive the response from server.. it returns null for each of the keys in the object returned.

Please help how do I solve this kinda issue. How do I stop it from returning until the response is not received from the API.

resolve() {
  this._apiFactory.getA().subscribe(response => {
     responseA = response;
  });
  this._apiFactory.getB().subscribe( response => {
     responseB = response;
  });
  this._apiFactory.getC().subscribe( response => {
     responseC = response;
  });

  return {
    'A': responseA ,
    'B': responseb ,
    'C': responseC 
  };
}
1

4 Answers 4

6

You were returning the before your subscriptions could get finished. Used Fork Join to wait until all your Get requests are completed and then returning the result of the get requests in your required format..

Update

Since Rxjs 6.5.0, forkJoin also accepts an object as an argument.

// dummy Observables
const obsArg = {
    A: of([1]).pipe(delay(1000)),
    B: of([1, 2, 3]).pipe(delay(2000)),
    C: of([1, 2, 3, 4]).pipe(delay(3000))
}

return forkJoin(obsArg)

I tried it in Angular 6 and I was able to do it like:

// dummy Observables
let a  = of([1]).pipe(delay(1000));
let b  = of([1, 2, 3]).pipe(delay(2000));
let c  = of([1, 2, 3, 4]).pipe(delay(3000));

 let join = forkJoin(a,b,c).pipe(map((allResponses) => {
   return {
     A: allResponses[0],
     B: allResponses[1],
     C: allResponses[2]
   };
 }));

 return join;

So, I manipulated the data in forkJoin and returned the forkJoin itself. see it here: https://stackblitz.com/edit/angular-xepafp?file=src%2Fapp%2FAPIResolver.ts

In angular2, something like this should work:

resolve() {
    return Observable.forkJoin(
      this._apiFactory.getA(),
      this._apiFactory.getB(),
      this._apiFactory.getC()
    ).map((allResponses) => {
       return {
         A: allResponses[0],
         B: allResponses[1],
         C: allResponses[2]
       };
     })
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Aashish, but it is still not helping. As you see it is a router resolve method which I am using for the first time. And I see that the router returns a nested observable rather then returning this object even before the forkJoin ends
@JEETADHIKARI: See the update, I took it from stackoverflow.com/questions/39066604/… , I think first() should be fine here.
Hey Ashish. Thankyou so much. That solved the problem. :)
3

As of RxJS 6.5+ the way to do it is:

return forkJoin({
  todos: timer(500).pipe(mapTo([{ title: 'forkJoin'}])),
  user: timer(500).pipe(mapTo({ id: 1 }))
});

Comments

0

This can be done with combineLatest as well. See this stackblitz

import { Injectable } from "@angular/core";
import { Resolve, ActivatedRouteSnapshot } from "@angular/router";
import { of, combineLatest } from "rxjs";
import { delay } from "rxjs/operators";

@Injectable({
  providedIn: "root"
})
export class TestResolver implements Resolve<any> {
  constructor() {}

  resolve(route: ActivatedRouteSnapshot) {
    let a = of([1]).pipe(delay(1000));
    let b = of([1, 2, 3]).pipe(delay(2000));
    let c = of([1, 2, 3, 4]).pipe(delay(3000));

    return combineLatest(a, b, c);
  }
}

Comments

0

Please Don't use Subscribe instead you can return your observables as

let a= observable(1);
let b= observable(2);
let c= observable(3);
return forkJoin(a,b,c);

this will help you

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.