Angular / rxJs concatMap-进行两个Web api(http)调用,要么不完成,要么控制移至后续行

问题描述 投票:0回答:1

我正在尝试在我的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);      
}
angular rxjs pipe observable tap
1个回答
0
投票

我看到三个成员变量this.autoRenewalEnabledthis.autoRenewalCheckingFrequencyInHoursthis.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...');
    }
  });

同样,依赖于这三个变量中的任何一个的所有代码都必须位于订阅中。

© www.soinside.com 2019 - 2024. All rights reserved.