derrickrozay
derrickrozay

Reputation: 1046

Resolve doesn't wait for API call to complete before falling to end of function

I am making an Angular 4 web app. I have a page that needs to wait for data before displaying so I'm using resolve. First resolve checks if the data is available in storage, if it is check if the ids in the route and data match, if not, retrieve the data from the API, and finally if the data does not exist in storage retrieve it from the API. However the function always falls to the end if API calls are made. What am I doing wrong?

resolve(route: ActivatedRouteSnapshot): Observable<PDataInterface>
{
  const routeID = route.params.id;
  // get data from storage
  this.getData();
  if (!!this.pData) {
    if (this.pData.id == routeID) {
      return Observable.of(this.pData);
    } else {
      this.API.getInfo(this.routeID).subscribe((data) => {
        this.pData = data;
        return Observable.of(this.pData);
      });
    }
  } else {
    this.API.getInfo(this.pData.id).subscribe((data) => {
      this.pData = data;
      return Observable.of(this.pData);
    });
  }
  // function always comes here if API calls are made
  console.log("failed resolve");
  this.router.navigate(['/dashboard']);
}

api.ts

getInfo(id) {
    const URL = `${this.API}/paintline/${id}`;
    return this.refreshToken()
      .flatMap(() => this.authHttp.get(URL, this.headers))
      .map((response: Response) => response.json().data)
      .share()
      .catch(this.handleError);
}

This is the refreshToken() that is called in getInfo(). It refreshes my JWT token if its expired before making the request to the backendd

refreshToken(): Observable<any>
{
  const URL = `${this.API}/refresh?token=${this.token}`;
  if (this.jwtHelper.isTokenExpired(this.token)) {
    return this.authHttp.get(URL)
      .map((rsp) =>
        {
          this.setToken(rsp.json().token);
          this.authNotifier.next(true);
          return rsp.json().token;
        },
        err =>
        {
          this.authNotifier.next(false);
          this.logout();
          console.log(err);
        })
      .share();
  }
  else { return Observable.of(this.token); }
}

app.module.ts

RouterModule.forRoot([
{
        {
          path: 'details',
          component: PDetailsComponent,
          resolve: {pData: PResolverService}
        },
}]

Upvotes: 0

Views: 2770

Answers (1)

LLai
LLai

Reputation: 13416

When you subscribe to your api, your API is fired but the rest of the resolve code continues to execute. That is why it keeps reaching your console.log("failed resolve");. Instead you should return the api observable and let the resolver do the subscribe.

resolve(route: ActivatedRouteSnapshot): Observable<PDataInterface>
{
    const routeID = route.params.id;
    // get data from storage
    this.getData();
    if (!!this.pData) {
        if (this.pData.id == routeID) {
            return Observable.of(this.pData);
        } else {
            return this.API.getInfo(this.routeID);
        }
    } else {
        return this.API.getInfo(this.pData.id);
    }
}

Upvotes: 3

Related Questions