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'));
}
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()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With