【问题标题】:Getting response from async 1st api call(takes time to get the response) and passing it on to the 2nd async api in order to get the final response从异步第一个 api 调用获取响应(需要时间来获取响应)并将其传递给第二个异步 api 以获得最终响应
【发布时间】:2019-09-30 11:04:41
【问题描述】:

第一次和第二次 api 调用都是后调用

someFunction(floor){
floor.entities.forEach(elementId => {
                        let desiredTempForZone;
                        this.getDesiredHeatingTemp(elementId._id).subscribe((des) => 
                                {
                                    desiredTempForZone = des
                                });
                        console.log(desiredTempForZone);
})
}

getDesiredHeatingTemp(eleId){
    //1st api call
    return this.siteService.getScheduleParamsByRoomRef('temp and air and desired and heating', eleId)
    .pipe(
    switchMap(a => {
        console.log(a)
        const obs = a.forEach((m)=>{
          //console.log(m)

        //this is custom function
        let pointId = this.helperService.stripHaystackTypeMapping(m.rows[0]['id']).split(' ')[0];

        //2nd api call
        return this.siteService.getHisPointData(pointId, 'current')
      })
      return forkJoin(obs)
  }))
}

我从第一个 api 调用得到的响应看起来像

a=
cols: (23) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
meta: {ver: "2.0"}
rows: [{…}]

a=
 cols: (23) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
 meta: {ver: "2.0"}
 rows: Array(1)
      0:
       air: "m:"
       desired: "m:"
       id: "r:5d906-9600-desire"
       kind: "Number"
       __proto__: Object
       length: 1
       __proto__: Array(0)

//第二次api调用

  return this.siteService.getHisPointData(pointId, 'current').subscribe(e => console.log(e))

问题
我也能够从第二个 api 调用中获得响应,但只有当我订阅(如上所述)到 (getHisPointData) api 而我想将此响应传递给 obs 时反过来被传递给下面的调用函数

this.getDesiredHeatingTemp(elementId._id).subscribe((des) => 
                                {
                                    desiredTempForZone = des
                                });

但是 obs 是未定义的

第二次api调用响应

       {meta: {…}, cols: Array(2), rows: Array(1)}
     cols: (2) [{…}, {…}]
     meta: {ver: "2.0", id: "r:5d8df1fc3942df083a4539d5", hisStart: "n:0.0", hisEnd: "n:0.0"}
     rows: Array(1)
        0:
          ts: "t:2019-09-30T13:40:58.761Z UTC"
          val: "n:65"
          __proto__: Object
          length: 1
        __proto__: Array(0)
    __proto__: Object
   {meta: {…}, cols: Array(2), rows: Array(1)}
     cols: (2) [{…}, {…}]
     meta: {ver: "2.0", id: "r:5d8df1fc3942df083a4539d5", hisStart: "n:0.0", hisEnd: "n:0.0"}
     rows: Array(1)
        0:
          ts: "t:2019-09-30T13:40:58.761Z UTC"
          val: "n:70"
          __proto__: Object
          length: 1
        __proto__: Array(0)
    __proto__: Object
           {meta: {…}, cols: Array(2), rows: Array(1)}
     cols: (2) [{…}, {…}]
     meta: {ver: "2.0", id: "r:5d8df1fc3942df083a4539d5", hisStart: "n:0.0", hisEnd: "n:0.0"}
     rows: Array(1)
        0:
          ts: "t:2019-09-30T13:40:58.761Z UTC"
          val: "n:90"
          __proto__: Object
          length: 1
        __proto__: Array(0)
    __proto__: Object

我获得最终价值的旧实现

 this.siteService.getScheduleParamsByRoomRef('temp and air and desired and heating', eleId).subscribe(({ rows }) => {
       if (rows.length > 0) {
           rows.forEach((row) => {
               let pointId = this.helperService.stripHaystackTypeMapping(row['id']).split(' ')[0];

               this.siteService.getHisPointData(pointId, 'current').subscribe(({ rows }) => {
                   if (rows.length > 0) {
                       let HeatingDesired = this.helperService.stripHaystackTypeMapping(rows[0].val);

                   }
               });
           });

       }

   });

【问题讨论】:

  • 我认为应该是a.rows.forEach 而不是a.forEach
  • @YashRami,哦,是的,现在执行进入内部,我的错我错过了,但是请您再建议一件事,一旦执行进入内部,我可以获得 pointId 但第二个 api通话没有发生
  • 你确定吗?您是否在 chrome 中检查了您的网络选项卡检查是否有任何 api 调用?
  • @YashRami,我得到 obs,因为 undefined 将检查第二个 api 调用响应,将更新
  • @YashRami ,我检查了,第二次 api 调用发生但 obs 未定义,所以返回 forkJoin(obs) ,未定义,您能否建议,可能是什么问题

标签: angular rxjs observable


【解决方案1】:

你可以这样试试,

someFunction(floor){
floor.entities.forEach(elementId => {
  let desiredTempForZone;
   this.getDesiredHeatingTemp(elementId._id).subscribe((des) => 
   {
     desiredTempForZone = des
   });
 })
}

getDesiredHeatingTemp(eleId){
    //1st api call
    return this.siteService.getScheduleParamsByRoomRef('temp and air and desired and 
      heating', eleId)
    .pipe(
    switchMap(a => {
        let secondApiCallUrlList = [];
        const obs = a.rows.forEach((m)=>{
          //this is custom function
          let pointId = this.helperService.stripHaystackTypeMapping(m.rows[0] 
            ['id']).split(' ')[0]; // here we dont need to create the asynchronisation block because as you said before older implemention is working as expected 

        //2nd api call
       secondApiCallUrlList.push(this.siteService.getHisPointData(pointId, 'current'));
      })
      return forkJoin(secondApiCallUrlList); // so here we are passing the whole array so while you subscribe you will get all response once all api call finished 
  }))
}

如果它没有醒来,请告诉我:)

【讨论】:

  • sry 没找到你,我们正在为第二个 api 调用创建一个 url 列表,我们如何获得第一个 api 响应
  • 你在这个订阅this.getDesiredHeatingTemp(elementId._id).subscribe((des) => { ... } 中得到这个未定义的?
  • 你可以尝试订阅des 这样des.subscribe(response => { console.log(response); }) 让我知道结果
  • Forkjoin 是返回包含所有 api 调用响应的观察者,这就是为什么
  • @Enthu 肯定的朋友
【解决方案2】:

第一个问题,这里:

const obs = a.forEach((m)=> {

那将是 undefined,因为 undefinedforEach 返回的唯一内容。您需要改用map

const obs = a.map((m) => {

forkJoin 返回的 observables:

return forkJoin(...obs)

someFunction 的模式相同:map 将数组转换为 observables 数组(不要在映射函数中订阅,返回 observables,而不是订阅),forkJoin创建 observables 数组,最后订阅并消费结果。

【讨论】:

  • 感谢您指出基本的事情 forEach 不返回任何东西
  • 这部分我相信我需要照顾,“和 someFunction 的相同模式:将一个数组映射到一个可观察的数组”
猜你喜欢
  • 2019-11-26
  • 2020-04-12
  • 2021-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多