首页 > 解决方案 > 使用 Observables 为循环迭代中的每个元素分配从 api 调用接收的值

问题描述

我有一个 foreach 循环,我正在迭代并希望调用函数,这些函数将依次进行异步 api 调用并返回可以在 html 中呈现的值。

第一个函数调用getCurrentValue()将返回 currentTemperatureRef ,我最终想分配receivedCurrentValue并在 html 中呈现

第二个函数调用getDesiredValue1()将返回desiredValueToBeReturned,我最终想分配receivedDesiredValue1并在 html 中呈现

ts

myObj = { droppedItem: [] };
elements = [
   { elementId: 1, elementName: "name1" },
   { elementId: 2, elementName: "name2" },
   { elementId: 3, elementName: "name3" },
   { elementId: 4, elementName: "name4" }
 ];

this.elements.forEach(element => {

    let receivedCurrentValue = this.getCurrentValue(element.name);
    let receivedDesiredValue1 = this.getDesiredValue1(element.id);


 this.myObj.droppedItem.push(receivedCurrentValue)
 this.myObj.droppedItem.push(receivedDesiredValue1)

}

getCurrentValue(eleName){

 //1st api(async api call)
 var ref = this.helperService.getPointIdbyTags(this.existingObj, ['current', 
          'temp'], eleName)[0];

 //2nd api(async api call which expects ref value from above api call)
 this.siteService.getHisPointData(ref, 'current')
                    .pipe(
                        map(this.helperService.stripHaystackTypeMapping),
                    )
                    .subscribe(({ rows }) => {
                        if (rows.length > 0) {
                            this.currentTemperatureRef = rows[0].val;
                        }
                    });
}

getDesiredValue1(eleId){
 //1st async api call
 this.siteService.getScheduleParamsByRoomRef('temp and air and desired and 
 heating', eleId)
   .subscribe(function (a) {
    let row = a;

      let pointId = this.helperService.stripHaystackTypeMapping(row['id']).split(' ')[0];

      //2nd async api call expecting pointId from above api call
       this.siteService.getHisPointData(pointId, 'current')
         .subscribe(function (a) {
                    let rows = a.rows,
                    if (rows.length > 0) {
                    let desiredValueToBeReturned = rows[0].val;
            )
           }
  )
 }
}    

html

<div *ngFor="let existingItem of myObj?.droppedItem">
<span>{{existingItem.receivedValue}}</span>
<span>{{existingItem.receivedDesiredValue1}}</span>
<span>{{existingItem.receivedDesiredValue2}}</span>
</div>

更新

当我尝试

getCurrentValue(eleName){
    let roomObj = this.getRoomObj(eleName);
    let equipRef = roomObj.map(equip => equip.entities.filter(entity => entity.entities.length > 0)[0])[0];

    return this.helperService.getPointIdbyTags(this.buildings, ['current', 
             'temp'], equipRef.referenceIDs.room)[0].pipe(switchMap((res:any)=>{
                   //we don't want "res" else the response of 
                   return  this.siteService.getHisPointData(res, 'current')
                       .pipe(
                           map(this.helperService.stripHaystackTypeMapping),
                       )
              }));
}

我在线收到错误=> return this.helperService.getPointIdbyTags(this.buildings, ['current', 'temp'],equipRef.referenceIDs.room)[0].pipe(switchMap(

错误类型错误:this.helperService.getPointIdbyTags(...)[0].pipe 不是函数

标签: javascriptangularobservable

解决方案


我不太了解这个问题,但是您需要了解一些有关 forkJoin 和 switchMap 的知识。SwitchMap 当您需要根据另一个的响应进行两次调用时,它很有用。建筑变得像

callOne.pipe(
  switchMap(resposeOfCallOne=>{
      return callTwo(responseOfCallOne)
  })

如果订阅您收到 callTwo 的响应

forkJoin 获取调用数组并在数组中返回结果

forkJoin([callOne,callTwo])

如果订阅你收到一个数组: res[0] 有 callOne 的响应, res[1] 有 callTwo 的响应

好吧,首先将您的函数 getCurrentValue 和 getDesiredValue1 转换为返回 observables

getCurrentValue(eleName){

 return this.helperService.getPointIdbyTags(this.existingObj, ['current', 
          'temp'], eleName)[0].pipe(switchMap((res:any)=>{
                //we don't want "res" else the response of 
                return  this.siteService.getHisPointData(ref, 'current')
                    .pipe(
                        map(this.helperService.stripHaystackTypeMapping),
                    )
           };
}

getDesiredValue1(eleId){
 return this.siteService.getScheduleParamsByRoomRef('temp and air and desired and 
 heating', eleId).pipe(
      switchMap((a:any)=>{
        let row = a;
        let pointId = this.helperService.stripHaystackTypeMapping(row['id']).split(' ')[0];
        return this.siteService.getHisPointData(pointId, 'current')
      }))

好吧,当我们有一个想要创建两个调用的元素时,我们将使用 forkjoin

我们要制作,forEach 元素创建两个调用,所以我们可以制作

this.elements.forEach(element => {
   forkJoin([this.getCurrentValue(element.name),this.getDesiredValue1(element.id)])
    .subscribe(([current,desired])=>{
        element.current=current;
        element.desired=desired;
    })
})

我订阅用户 ([current,desired]) 但我们可以使用 res 并使用 element.current=res[0],element.desired=res[1]

如果我们愿意,我们甚至可以只订阅一个——现在我们有这么多订阅元素——

arrayOfCalls=[]
this.elements.forEach(element => {
   arrayOfCalls.push(
     forkJoin([this.getCurrentValue(element.name),this.getDesiredValue1(element.id)])
   )
}
//then subscribe
arrayOfCalls.subscribe((fullRes:any[])=>{
    fullRes.map((res,index)=>{
       this.elements[index].currentValue=res[0]
       this.elements[index].desiredValue=res[1]
    })
})

推荐阅读