Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 subscribe inside subscribe

In Angular2, what would be the correct way to implement a second API call based on the result from the first API call? One of my Angular2 components has the following method. I tried with having a subscribe inside another subscribe on complete and the response from the second subscribe is always 'undefined'.

Edit based on suggestion from CozyAzure.

export interface Result {
  host: string;
  resourceUri: string;
  groupId?: string;
  resource?: any;
}

private curateResults(searchTerm: string, searchResults: SearchResults): Result[] {
    const results: Result[] = [];
    if (searchResults.results !== undefined && searchResults.results.length > 0) {
      searchResults.results.forEach((result: any) => {
        const processedSearchResult: Result = {
          host: result.origin.toString(),
          resourceUri: result.url.toString()
        };
        processedSearchResult.resource = undefined;
        processedSearchResult.groupId = undefined;
        this.bopsHttpService.getResourceData(processedSearchResult.host, processedSearchResult.resourceUri)
          .flatMap((resource: any) => {
            processedSearchResult.groupId = this.getGroupIdFromResource(resource, 'groupId');
            if (processedSearchResult.groupId === undefined) {
              const uriParts = processedSearchResult.resourceUri.split('/');
              const predicate = uriParts[uriParts.length - 2];
              if (predicate === 'group') {
                processedSearchResult.groupId = uriParts[uriParts.length - 1];
                return Observable.empty();
              } else {
                return this.bopsHttpService.getGroupRelation(processedSearchResult.resourceUri.split('/').pop());
              }
            } else {
              return Observable.empty();
            }
          })
          .subscribe((relation: any) => {
            if (relation !== undefined) {
              processedSearchResult.groupId = relation.objectId;
              console.log('Fetched Group ID: ', processedSearchResult.groupId);
            }
          });
        results.push(processedSearchResult);
      });
    }
  return results;
}

My http calls are as follows:

  public getGroupRelation(subjectId: string): Observable<Relation> {
    const path = `${this.bopsServiceUrl}/relation/${subjectId}/group`;
    const queryParameters = new URLSearchParams();
    queryParameters.set('at', new Date().toISOString());
    const options = new RequestOptions({
      headers: this.headers,
      search: queryParameters
    });
    return this.http.get(path, options)
      .map((response: Response) => response.json())
      .catch((error: any) => Observable.throw(error.json().error
        || 'BOPS Server error during get group relation Operation', 
          error.json()));
  }

  public getResourceData(host: string, resourceUri: string): Observable<any> {
    const path = host + resourceUri;
    const queryParameters = new URLSearchParams();
    queryParameters.set('at', new Date().toISOString());
    const options = new RequestOptions({
      headers: this.headers,
      search: queryParameters
    });
    return this.http.get(path, options)
      .map((response: Response) => response.json())
      .catch((error: any) => Observable.throw(error
        || 'BOPS Server error during Get Resource Data Operation'));
  }
like image 856
RKG Avatar asked Jun 29 '17 17:06

RKG


1 Answers

You will need to use .flatMap() if you want to chain your Observables. flatMap() is the same as .then() if you are thinking of the Promise way.

Do this instead:

this.bopsHttpService.getResourceData(processedSearchResult.host, processedSearchResult.resourceUri)
    .flatMap(() => {
        //check if groupId exist, or whatever your logic is
        if(hasGroupId){
            //groupId exist, proceed to call your second request
            return this.bopsHttpService.getGroupRelation(processedSearchResult.resourceUri.split('/').pop());
        }
        //groupId doesn't exist, return an empty Observable.
        return Observable.empty();

    })
    .subscribe((relation) => {
        if (relation !== undefined) {
            processedSearchResult.groupId = relation.objectId;
            console.log('Fetched Group ID: ', processedSearchResult.groupId);
        }
    })

Edit:

You can do any interventions inside your flatMap() callbacks. You can check if the groupId exist or not, only then you proceed to your next call. If it doesn't, simply returns an empty Observable using Obersvable.empty().

like image 169
CozyAzure Avatar answered Oct 10 '22 04:10

CozyAzure