Angular/rxJs concatMap - 进行两次网络 api (http) 调用,要么不完成,要么控制移动到后续行
Angular/rxJs concatMap - making two web api (http) calls, either dont finish and control move to subsequent lines
我正在尝试在我的 angular 9 应用程序中使用 rxJs concatMap。基本上我需要使用 http 进行两次 Web api 调用,两者都是 return 可观察值,填充其他值。第一次调用需要 return 一些值,这些值将用作第二次 api 调用的参数,然后应该继续。我尝试使用 tap 为此使用 concatMap,但没有成功。当调用方法(checkForRenewal())时,第一行被命中,但等待 api 调用完成或转到第二个 api 调用,它移动到其他行。
程序要么没有等待第一个完成,要么第二个调用没有正确执行,并且控件移至下一行(在 2 个网络 api 调用之后)。几秒钟后,我看到第一个 API 被触发并读取了值,但为时已晚。
我在 contactMap 之后还有其他 api 个电话...但不包括此 post。
如何实现这个或者有什么问题?我需要在 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...');
}
});
同样,依赖于这三个变量中任何一个的所有代码都必须在订阅内。
我正在尝试在我的 angular 9 应用程序中使用 rxJs concatMap。基本上我需要使用 http 进行两次 Web api 调用,两者都是 return 可观察值,填充其他值。第一次调用需要 return 一些值,这些值将用作第二次 api 调用的参数,然后应该继续。我尝试使用 tap 为此使用 concatMap,但没有成功。当调用方法(checkForRenewal())时,第一行被命中,但等待 api 调用完成或转到第二个 api 调用,它移动到其他行。
程序要么没有等待第一个完成,要么第二个调用没有正确执行,并且控件移至下一行(在 2 个网络 api 调用之后)。几秒钟后,我看到第一个 API 被触发并读取了值,但为时已晚。
我在 contactMap 之后还有其他 api 个电话...但不包括此 post。
如何实现这个或者有什么问题?我需要在 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...');
}
});
同样,依赖于这三个变量中任何一个的所有代码都必须在订阅内。