我正在尝试在我的angular 9应用程序中利用rxJs concatMap。基本上,我需要使用http进行两次Web api调用,两者均返回observables,并填充其他值。第一次调用需要返回一些值,这些值将用作第二次api调用的参数,然后应该继续。我试图通过使用tap来使用concatMap,但是没有运气。调用method(checkForRenewal())时,第一行被命中,但等待api调用完成或转到第二个api调用,它将移至其他行。
程序不是在等待第一个调用完成,并且第二个调用无法正确执行,并且控件移至下一行(在两次Web api调用之后)。几秒钟后,我看到第一个API被触发并读取了值,但是为时已晚。
我在contactMap之后还有其他api调用...,但不包括在这篇文章中。
如何实现这一目标或出了什么问题? concatMap之后是否需要最终订阅?下面的示例代码。
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);
}
我看到三个成员变量this.autoRenewalEnabled
,this.autoRenewalCheckingFrequencyInHours
和this.skipKeyRenewal
在异步调用中被分配了值。这些变量被异步分配值。因此,当您尝试在订阅之外访问它时,可能尚未为其分配值。尝试在订阅之外访问this.skipKeyRenewal
时可以看到该问题。它实际上应该在订阅中]
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...');
}
});
同样,依赖于这三个变量中的任何一个的所有代码都必须位于订阅中。