如何使用interval更新一个observable数组?

时间:2016-10-24 19:49:56

标签: javascript angular rxjs rxjs5

我正在尝试使用angular 2和chart.js(通过ngcharts)为图表构建仪表板。我想要一个图表数组,每个图表都通过自定义间隔的http请求进行更新。

现在我有三个单独的图表调用将数据推送到数组。我在下一次迭代时遇到了麻烦 - 如果我再次推送到阵列,我最终会再增加3个图表。我希望数组中的订阅者在间隔发出时使用新数据进行更新。

我对如何正确构建我的用例的组件/服务/ http关系感到困惑。我觉得我很亲密,但我肯定错过了一些东西。如何让间隔/订户关系映射到视图并在一定时间间隔内更新现有图表? 任何帮助都会很棒!

现在:

服务

我在这里实施间隔:

import { Component } from '@angular/core';
import { ChartsModule } from 'ng2-charts/ng2-charts';
import { ChartService } from './chart.service';
import { Graph } from './graph';
import { OnInit } from '@angular/core';
import { Observable } from 'rxjs/Rx';


@Component({
  selector: 'ab-chart',
  styles: [`
    .chart {
      display: block;
    }
  `],
  templateUrl: 'app/chart.component.html'
})
export class ChartComponent implements OnInit {

    ngOnInit(): void {
      console.log("Chart component init");

      this.getSingleChart(3, 5000);
      this.getSingleChart(5, 4000);
      this.getSingleChart(6, 5000);
    }

    graph: Graph;
    graphs: Graph[] = [];


    constructor(
        private chartService: ChartService
    ) {}


  getSingleChart(id: number, interval: number): void {
     this.chartService.getSingleChartObsinterval(id, interval)
      .subscribe(x => 
       this.graphs.push(x)
      );
}
}

extractJsonData只是接受响应并操纵它以使用图表JS。它返回一个Graph对象,该对象具有易于使用的属性。我无法控制API,因此我无法重新配置响应以包含多个图表。

组件:

<div *ngFor="let graph of graphs" class="chart-container">
    <base-chart
        class="chart"
        [datasets]="graph.datasets"
        [labels]="graph.labels"
        [options]="graph.options"
        [chartType]="graph.type">
      </base-chart>
  </div>

观点:

contact_id |  phone_number 
         1 |  55551002
         1 |  55551003
         1 |  55551000
         2 |  55552001
         2 |  55552008
         2 |  55552003
         2 |  55552007
         3 |  55553001
         3 |  55553002
         3 |  55553009
         3 |  55553004
         4 |  55554000

2 个答案:

答案 0 :(得分:1)

你的图表数量有限吗?如果你总是有三个,你可以利用combineLatest运算符(如果你有更多,你必须使用某种形式的递归)。

在您的组件中,您可以执行以下操作:

 this.graphs = this.getSingleChart(3, 5000).combineLatest(
        this.getSingleChart(5, 4000),
        this.getSingleChart(6, 5000),
        (val1, val2, val3) => return [val1, val2, val3])
        //.subscribe((arrayOfVal) => console.log(arrayOfVal);

每次更新其中一个图表时,这将返回一个新数组。如果图表2获得一个新值,则将使用旧值1,新值2和旧值3调用函数(combineLatest的第三个参数)。

在你的模板中你可以使用它:

 <div *ngFor="let graph of graphs | async" ...>

CombineLatest:https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/combinelatest.md

答案 1 :(得分:1)

由于每个图都有自己的id(我假设它是唯一的)所以我只需更改getSingleChart()方法来更新特定键的graphs对象。注意我将graphs属性从数组更改为对象:

graphs: {[key: number]: Graph} = {};

getSingleChart(id: number, interval: number): void {
  this.chartService.getSingleChartObsinterval(id, interval)
    .subscribe(x => this.graphs[id] = x);
}

get graphIds() {
    return Object.keys(this.graphs);
}

然后在模板中,您需要迭代键数组(您可以迭代graphs对象:

<div *ngFor="let id of graphIds" class="chart-container">
    <base-chart
        class="chart"
        [datasets]="graphs[id].datasets"
        [labels]="graphs[id].labels"
        [options]="graphs[id].options"
        [chartType]="graphs[id].type">
    </base-chart>
</div>