Присвоение значений, полученных из вызовов API, для каждого элемента в итерации цикла с использованием Observables - PullRequest
0 голосов
/ 29 сентября 2019

У меня есть цикл foreach, через который я выполняю итерации и хочу вызывать функции, которые, в свою очередь, будут выполнять асинхронные вызовы API и возвращать значение, которое может быть отображено в html.

1-й вызов функции getCurrentValue () вернул бы currentTemperaRef, который я наконец хочу присвоить receiveCurrentValue и отобразить в html

2-й вызов функции getDesiredValue1 () вернул бы requiredValueToBeReturned , который я, наконец, хочу назначить receiveDesiredValue1 и рендерить в 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),
                       )
              }));
}

Я получаю сообщение об ошибке в строке => вернуть this.helperService.getPointIdbyTags (this.buildings, ['current', 'temp'], equipRef.referenceIDs.room) [0] .pipe (switchMap (

ОШИБКА TypeError: this.helperService.getPointIdbyTags (...) [0] .pipe не является функцией

1 Ответ

2 голосов
/ 29 сентября 2019

Я не так много понимаю вопроса, но вам нужно кое-что понять о forkJoin и switchMap. SwitchMap полезно, когда вам нужно сделать два вызова один, в зависимости от ответа другого. Конструкция выглядит так:

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

Если подписаться вы получили ответ callTwo

forkJoin, получите массив вызовов и вернете результат в массив

forkJoin([callOne,callTwo])

, еслиподписаться вы получили массив: res [0] имеет ответ callOne и res [1] ответ callTwo

Что ж, сначала преобразуйте ваши функции getCurrentValue и getDesiredValue1, чтобы вернуть наблюдаемые значения

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;
    })
})

Я использую подписку ([текущий, желаемый]), но мы можем использовать 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]
    })
})
...