javascript - 已经完成 Angular 取数据后如何将数据一一显示

标签 javascript angular typescript

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已经完成获取数据时,就会显示它。而另一个仍在加载/获取。

就像区域 1 已经完成获取,然后是区域 3、区域 2、区域 5、区域 4。

谁完成抓取就会自动显示。

最佳答案

我会通过两种方式之一来解决这个问题。两者都不涉及 promise 。

我不会尝试使用您的代码示例,因为它太大了,相反,我将重点关注问题的核心 - 运行可观察数组并在返回结果时对其进行处理。

<强>1。合并可观察量

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

专业版:订阅中处理结果简单

缺点:必须在完整回调中运行完整代码

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

专业版:订阅中简单完整的处理

Con 各个 tap 运算符中的处理结果可能会有点困惑

结论

这两种方法相当等效。我可能更喜欢 forkJoin 方法,但我想通过提供第二个示例来展示 RxJS 的强大功能和灵 active 。

演示:https://stackblitz.com/edit/angular-7rrmtn

该演示设置了 5 个可观察量,每个观察量都有不同的延迟。可观察量在结果返回时进行处理,并在完成时进行记录。

如您所见,它们在功能上是等效的。

关于javascript - 已经完成 Angular 取数据后如何将数据一一显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61074341/

相关文章:

javascript - NestJs:如何在实体监听器中访问数据库?

angular - 在 Angular 2 中从父容器调用子容器中的函数

包含多个条件的 JavaScript 查找失败

javascript - 水平滚动一个div到某个类名

javascript - 在 AWS Lambda 中使用 NodeJS 将 Woocommerce API 函数更改为异步/等待

Angular 4 webpack sass sourcemap 文件几乎是空的(使用 ExtractTextPlugin)

java - 是否可以在没有用户操作的情况下上传文件,或者只是 html、Angular 中的对话框?

angular - 如何使用动态值将 "name"属性添加到 <mat-cell> 或 <mat-row>?

angular - Angular 6 中的搜索过滤器

javascript - jQuery 可排序、可调整大小、可拖动的调整大小问题