I am trying to utilize rxJs concatMap inside my angular 9 application. Basically I need to make two web api calls using http, both return observables, populate other values. The first call need to return some values, which will be used as parameter for second api call and then supposed to continue. I tried to utilize the concatMap for this using tap, but no luck. When the method(checkForRenewal()) is called, the first line gets hit, but waiting for completion of api call or go to second api call, it moves to other lines.
The program is either not waiting for the first to finish and second call don't execute correctly and the control move to next lines (after 2 web api calls). After few seconds, I see the first API is triggered and the values are read, but it is too late.
I have other api calls following the contactMap...but excluding from this post.
How to achieve this or what is wrong? Do i need a final subscribe after concatMap? Sample code below.
checkForRenewal(): void {
this.ls.getSoftwareModules() //first web api call
.pipe(
tap((data) => {
{
try {
const dataXml = data.filter((data) => data.SoftwareModuleName == 'Activation')[0].XmlConfig;
if (dataXml) {
const config = xmlToJson(dataXml);
this.autoRenewalEnabled =
config['configuration'].appSettings.param.filter(
(data) => data.name == 'AutoRenewalEnabled',
)[0].value === 'true';
this.autoRenewalCheckingFrequencyInHours = config[
'configuration'
].appSettings.param.filter(
(data) => data.name === 'AutoRenewalCheckingFrequencyInHours', //this line not hitting first, but later gets hit
)[0].value;
}
} catch (e) {
}
}
}),
concatMap(() => this.ls.checkForRenewalAlreadyRan(this.autoRenewalCheckingFrequencyInHours, true)), //2nd web api call
tap((data2) => {
this.skipKeyRenewal = data2;
console.log('checkForRenewalAlreadyRan-->' + data2);
}),
)
.subscribe((resp) => {
console.log(resp);
});
if (this.skipKeyRenewal) { //issue ...control seem to reach here first before making the above api calls using concatMap
console.log('auto renewal program already ran in last 24 hours, so processing will not resume!');
return;
} else {
console.log('process continue for auto renewal...');
}
this._activationService.getActivationSites().subscribe({
next: (resp) => {
this.sites = resp;
this.siteName = this.sites[0].SiteName;
this.siteID = this.sites[0].SiteID;
},
error: (err) => {
console.log(`err-->${err}`);
},
});
this._activationService.getUuidPartial().subscribe({
next: (resp) => {
this.hardwareID = resp;
this.decimalHardwareID = parseInt(this.hardwareID, 16);
},
error: (err) => {
console.log(`err-->${err}`);
},
});
hData = this._activationService.getProductActivations('ProductA', this.showKeys);
gData = this._activationService.getProductActivations('ProductB', this.showKeys);
//other stuff goes here on wards
==============================================
//two api calls returning observables in service ( lookup.service.ts)
//1st web api
getSoftwareModules(where: string = '', orderBy: string = ''): Observable<SoftwareModule[]> {
const url = `${this.config.host}${GLOBAL.SV_GET_MODULE_LIST}sessionID=${this.appSession.session.SessionID}&where=${where}&orderby=${orderBy}`;
return this.http.get<SoftwareModule[]>(url);
}
//2nd web api
checkForRenewalAlreadyRan(frequencyInHoures: number, isApiReady: boolean): Observable<boolean> {
const url = `${this.config.host}${GLOBAL.SV_GET_KEY_RENEWAL_SETTINGS}sessionID=${this.appSession.session.SessionID}&frequencyInHoures=${frequencyInHoures}&isApiReady=${isApiReady}`;
return this.http.get<boolean>(url);
}
I see three member variables this.autoRenewalEnabled
, this.autoRenewalCheckingFrequencyInHours
, and this.skipKeyRenewal
being assigned values inside the asynchronous calls. These variables are assigned values asynchronously. So when you try to access it outside the subscription, they may not be assigned the values yet. The issue can be seen in trying to access this.skipKeyRenewal
outside the subscription. It should actually be inside the subscription
this.ls.getSoftwareModules()
.pipe(
...
)
.subscribe((resp) => {
console.log(resp);
if (this.skipKeyRenewal) { //issue ...control seem to reach here first before making the above api calls using concatMap
console.log('auto renewal program already ran in last 24 hours, so processing will not resume!');
return;
} else {
console.log('process continue for auto renewal...');
}
});
Likewise all the code that depend on any of these three variables must be inside the subscription.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.