如何使用间隔更新可观察数组?
How to update an array of observables using interval?
我正在尝试使用 angular 2 和 chart.js(通过 ngcharts)为图表构建仪表板。我想要一组图表,每个图表都通过自定义间隔的 http 请求进行更新。
现在我有三个单独的图表调用将数据推送到一个数组。我在下一次迭代时遇到了麻烦——如果我再次推送到数组,我最终会得到另外 3 个图表。我希望数组中的订阅者在间隔发出时更新新数据。
对于如何为我的用例正确构建 component/service/http 关系,我有点困惑。我觉得我很接近,但我肯定错过了什么。如何获取 interval/subscriber 关系以映射到视图并定期更新现有图表?
任何帮助都会很棒!
现在:
服务:
我在这里实现间隔:
getSingleChartObsinterval(id: number, interval: number) : Observable<Graph> {
return Observable.interval(interval).flatMap(() => this.getSingleChartobs(id));
}
getSingleChartobs(id: number) : Observable<Graph> {
return this.jsonp.get(“api location”)
.map(response => this.extractJsonData(response, id) as Graph)
}
extractJsonData 只是获取响应并对其进行操作以与图表 JS 一起使用。它 returns 具有易于使用的属性的 Graph 对象。我无法控制 API,所以我无法重新配置响应以包含多个图表。
组件:
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)
);
}
}
观点:
<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>
您的图表数量有限吗?如果你总是有三个,你可以利用 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);
每当其中一个图表更新时,这将 return 一个新数组。如果图表 2 获得新值,函数(combineLatest 的第三个参数)将被调用,旧值 1,新值 2 和旧值 3。
在您的模板中,您可以只使用这个:
<div *ngFor="let graph of graphs | async" ...>
合并最新:https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/combinelatest.md
由于每个图都有自己的 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>
我正在尝试使用 angular 2 和 chart.js(通过 ngcharts)为图表构建仪表板。我想要一组图表,每个图表都通过自定义间隔的 http 请求进行更新。
现在我有三个单独的图表调用将数据推送到一个数组。我在下一次迭代时遇到了麻烦——如果我再次推送到数组,我最终会得到另外 3 个图表。我希望数组中的订阅者在间隔发出时更新新数据。
对于如何为我的用例正确构建 component/service/http 关系,我有点困惑。我觉得我很接近,但我肯定错过了什么。如何获取 interval/subscriber 关系以映射到视图并定期更新现有图表? 任何帮助都会很棒!
现在:
服务:
我在这里实现间隔:
getSingleChartObsinterval(id: number, interval: number) : Observable<Graph> {
return Observable.interval(interval).flatMap(() => this.getSingleChartobs(id));
}
getSingleChartobs(id: number) : Observable<Graph> {
return this.jsonp.get(“api location”)
.map(response => this.extractJsonData(response, id) as Graph)
}
extractJsonData 只是获取响应并对其进行操作以与图表 JS 一起使用。它 returns 具有易于使用的属性的 Graph 对象。我无法控制 API,所以我无法重新配置响应以包含多个图表。
组件:
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)
);
}
}
观点:
<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>
您的图表数量有限吗?如果你总是有三个,你可以利用 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);
每当其中一个图表更新时,这将 return 一个新数组。如果图表 2 获得新值,函数(combineLatest 的第三个参数)将被调用,旧值 1,新值 2 和旧值 3。
在您的模板中,您可以只使用这个:
<div *ngFor="let graph of graphs | async" ...>
合并最新:https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/combinelatest.md
由于每个图都有自己的 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>