Как отображать данные один за другим, когда их уже заканчивается sh выборки данных в angular - PullRequest
0 голосов
/ 07 апреля 2020

HTML

<div nz-row *ngIf="tempThermometer | async as temp">
<div *ngFor="let data of temp;let i = index;" nz-col nzXs="24" nzSm="12" nzMd="12" nzXl="8" nzXXl="6">
<nz-spin nzTip="Loading..." [nzSize]="'large'" [nzSpinning]="data.spinning">
                            <div echarts [options]="chartOption[i]" [autoResize]="true" style="height: 270px;"></div>
                          </nz-spin>
    </div>
    </div>

TS

 tempLoading = false;
  tempThermometer = new BehaviorSubject<any>([]);

getRoomList() {
    this.tempLoading = true;
    this.subscription = this.global
      .getData(`/conditions/latest?length=${this.pageSize}`)
      .pipe(take(1))
      .subscribe((res: any) => {
        this.tempThermometer.next(Object.values(res['data'].map((obj: any) => {
          return {
            ...obj,
            spinning: true
          };
        })));

        this.tempLoading = false;
        this.lineChart(this.tempThermometer.value);
      });
  }
lineChart(params?: any) {
    const _this = this;
    const list: any = [];

    params.forEach((param: any) => {
      const url = encodeURIComponent(param.sensor);
      // List URL
      list.push(`/conditions?length=${this.length}&sensor=${url}`);
    });
    // Promise requests
    const promises = list.map(
      (url: any) =>
        new Promise(resolve => {
        this.subscription =  this.global.getData(url).pipe(take(1)).subscribe((res) => {
            resolve(res);
          }, (err: Error) => {
            return reject(err);
          });
        })
    );
    // Retrieve each data as per promise
    Promise.all(promises).then(results => {
      const dataRoom: any = [];

      results.map((result) => {
        const date: any = [], temperature: any = [], humidity: any = [], newRoomData: any = [];
        const param = result['data'];
        const roomData = orderBy(param, ['date'], ['asc']);
        const room = roomData.slice(-1)[0];
        const timeEnd = room.date.slice(0, 19);
        const timeStart = subHours(timeEnd, 7);
        const dataHour = roomData.filter((data: TemplogRecord) => {
          return !isBefore(data.date, timeStart) && !isAfter(data.date, timeEnd);
        });

        // console.log(roomData);

        const hash = Object.create(null);

        dataHour.forEach((data: any) => {
          const key = data.date.slice(0, 13);

          if (!hash[key]) {
            hash[key] = {
              sensor: data.sensor, temperature: data.temperature,
              humidity: data.humidity, date: key + ':00:00'
            };
            newRoomData.push(hash[key]);
          }
        });

        for (let x = 0; x < newRoomData.length; x++) {
          temperature.push(newRoomData[x].temperature);
          humidity.push(newRoomData[x].humidity);
          date.push(newRoomData[x].date);
        }

        dataRoom.push({
          date: date,
          humidity: humidity,
          temperature: temperature
        });
      });

      dataRoom.forEach((param: any, index: number) => {
        const option = {
          tooltip: {
            trigger: 'axis',
            axisPointer: {
              animation: false
            },
            backgroundColor: 'rgba(245, 245, 245, 0.8)',
            borderWidth: 1,
            borderColor: '#ccc',
            padding: 10,
            textStyle: {
              color: '#000'
            },
            formatter: function (prm: any) {
              let rec = prm[0].name.slice(0, 10) + '<br/>' + prm[0].name.slice(11, 19) + '<br/>';

              for (let x = 0; x < prm.length; x++) {
                if (prm[x].axisIndex !== 1) {
                  rec += prm[x].marker + ' ' + prm[x].seriesName + ': '
                    + prm[x].data + _this.units['Celcius'] + '<br/>';
                } else {
                  rec += prm[x].marker + ' ' + prm[x].seriesName + ': '
                    + prm[x].data + '%' + '<br/>';
                }
              }
              return rec;
            }
          },
          ...this.echart.roomChart,
          dataZoom: [{
            type: 'inside',
            show: false,
            bottom: 0,
            width: '84%',
            xAxisIndex: [0, 1],
            zoomOnMouseWheel: false,
          },
          {
            type: 'slider',
            bottom: 0,
            show: false,
            width: '84%',
            xAxisIndex: [0, 1],
            zoomLock: false,
          }],
          xAxis: [{
            type: 'category',
            boundaryGap: false,
            scale: true,
            axisLine: {
              show: false
            },
            axisTick: {
              show: false
            },
            data: param.date.map((str: any) => {
              return format(str, 'YYYY-MM-DD hh:mm a');
            }),
            splitLine: {
              show: true,
              lineStyle: {
                color: 'rgba(182, 202, 227)'
              }
            },
            axisLabel: {
              show: true,
              interval: 0,
              rotate: 90,
              formatter: ((data: any) => {
                return (data).slice(11, 19);
              })
            }
          },
          {
            gridIndex: 1,
            show: false,
            scale: true,
            type: 'category',
            boundaryGap: false,
            axisLine: {
              show: false
            },
            data: param.date,
            axisTick: {
              show: false
            },
            splitLine: {
              show: true
            }
          }],
          series: [{
            name: 'Humidity',
            data: param.humidity,
            type: 'line',
            itemStyle: {
              color: 'rgba(0, 101, 144, 1)'
            },
            markPoint: {
              type: 'Pin',
              data: [
                {
                  type: 'max',
                  itemStyle: {
                    color: 'rgba(0, 101, 144)'
                  }
                },
                {
                  type: 'min',
                  itemStyle: {
                    color: 'rgb(110, 151, 204)'
                  }
                }
              ]
            },
            smooth: true,
            xAxisIndex: 1,
            yAxisIndex: 1
          },
          {
            name: 'Temperature',
            data: param.temperature,
            type: 'line',
            itemStyle: {
              color: 'rgba(255, 0, 0, 1)'
            },
            markPoint: {
              type: 'Pin',
              data: [
                {
                  type: 'max',
                  itemStyle: {
                    color: 'rgba(255, 5, 0)'
                  }
                },
                {
                  type: 'min',
                  itemStyle: {
                    color: 'rgb(255, 87, 86)'
                  }
                }
              ]
            },
            smooth: true
          },

          ]
        };
        this.chartOption.push(option);
        this.notScrolly = true;
        this.tempThermometer.value.filter((x: any) => params.map((y: any) => {
          if (y.id === x.id) {
            return y.spinning = false;
          }
        }));
      });
    });
  }

Проблема здесь в том, что при загрузке он извлекает все данные, прежде чем отобразит их все. То, что я хочу сделать здесь, это когда первый элемент, который уже извлекается, будет отображаться, в то время как другие все еще извлекают данные.

например, есть 5 элементов, которые представляют собой область 1, область 2, область 3, область 4 и область 5.

, когда область 1 уже закончила sh выборки данных, она отобразит их. в то время как другой все еще загружается / извлекается.

как область 1, уже завершенная sh выборка, затем следующая область 3, затем область 2, затем 5, затем 4.

кто когда-либо заканчивал sh выборка будет отображаться автоматически.

Ответы [ 2 ]

1 голос
/ 07 апреля 2020

Я бы подошел к этому одним из двух способов. Ни то, ни другое не потребует обещаний.

Я не буду пытаться использовать ваш пример кода, поскольку он слишком велик, вместо этого я сосредоточусь на сути вашей проблемы - запустите массив наблюдаемых и обработайте результаты как они возвращаются.

1. Объединить наблюдаемые

Функция Rx JS merge будет запускать несколько наблюдаемых вместе и немедленно вызывать ваш обратный вызов подписки с отдельными значениями.

const observables: Observable<any>[] = this.getObservables();
merge(...observables).subscribe(result => {
  // individual results are logged here as soon as the observable returns them
  console.log(result);
}, err => {
  // empty error callback. 
  // This is here to allow us to add the complete callback
}, () => {
  console.log('complete');
});

Pro : простота обработки результатов в подписке

Con : необходимо выполнить полный код при полном обратном вызове

2. Результаты обработки в трубе

Вы можете запустить наблюдаемые параллельно в forkJoin. Подписка будет вызвана только после завершения финальной наблюдаемой, но вы можете обработать результаты в отдельных tap операторах.

const observables: Observable<any>[] = this.getObservables()
  .map(x => x.pipe(
    // tap is run as soon as the observable is returned
    tap(result => console.log(result))
  ));
forkJoin(observables).subscribe(result => {
  console.log('complete');
});

Pro : простая полная обработка в подписке

Con обработка результатов в отдельных tap операторах может стать немного беспорядочной

Заключение

Оба эти подхода довольно эквивалентны. Вероятно, я бы предпочел подход forkJoin, но я хотел продемонстрировать мощь и гибкость Rx JS, приведя второй пример.

DEMO: https://stackblitz.com/edit/angular-7rrmtn

Демо-версия настраивает 5 наблюдаемых, каждая с разной задержкой. Наблюдаемые обрабатываются по мере того, как возвращаются результаты, и они оба регистрируются по завершении.

Как вы можете видеть, они функционально эквивалентны.

0 голосов
/ 07 апреля 2020

Попробуйте добавить изменить стратегию обнаружения и запустить функцию detectChanges , как только вы обновите переменную с первой точкой данных

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...