Javascript 如何使用间隔更新观察值数组?

Javascript 如何使用间隔更新观察值数组?,javascript,angular,rxjs,rxjs5,Javascript,Angular,Rxjs,Rxjs5,我正在尝试使用angular 2和chart.js(通过ngcharts)构建图表的仪表板。我希望有一个图表数组,每个图表都可以通过http请求按自定义间隔进行更新 现在我有三个单独的图表调用,它们将数据推送到一个数组中。在下一次迭代时,我遇到了麻烦-如果我再次推到数组,我将得到另外3个图表。我希望阵列中的订阅服务器在间隔发出新数据时使用新数据进行更新 对于如何为我的用例正确构造组件/服务/http关系,我有点困惑。我觉得我很接近,但我肯定错过了什么。如何使间隔/订户关系映射到视图并在间隔上更新

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

现在我有三个单独的图表调用,它们将数据推送到一个数组中。在下一次迭代时,我遇到了麻烦-如果我再次推到数组,我将得到另外3个图表。我希望阵列中的订阅服务器在间隔发出新数据时使用新数据进行更新

对于如何为我的用例正确构造组件/服务/http关系,我有点困惑。我觉得我很接近,但我肯定错过了什么。如何使间隔/订户关系映射到视图并在间隔上更新现有图表? 任何帮助都会很好

现在:

服务:

<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>
我在这里实现了间隔:

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)
}
视图:

<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>

您的图表数量有限吗?如果你总是有三个,你可以利用
combinelateest
操作符(如果你有更多,我想你必须使用某种形式的递归)

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

 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调用函数(CombineTest的第三个参数)

在模板中,您可以只使用以下内容:

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


CombineTest:

因为每个图都有自己的
id
(我假设它是唯一的),所以我只需更改
getSingleChart()
方法,以更新特定键处的
对象。注意:我将
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);
}
然后在模板中,您需要迭代键数组(您可以迭代
图形
对象:

<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>


你不能用新数据替换现有图形,而不是在数组中推送新图形吗?我对chart.js一无所知,因此可能无法替换他的数据,而只是等待angular渲染新图形chart@No我想这就是我要问的。每个图表都有不同的间隔,所以我很高兴我可以让数组中的每个项订阅更改并更新自身,而不必吹走数组。我尝试将每个对象作为订阅方推送到数组中,但没有成功。我希望有一种方法可以做到这一点,而不必搜索数组中的ID并自己更新数据。实际上,这不会像这样工作,因为se
CombineTest()
返回一个可观测值,而不是回调返回的值。这也意味着您总是必须一次刷新所有图表。它确实会返回一个可观测值。但是,这是一个要点,在这种情况下,可观测值可以在模板中与异步管道一起使用。CombineTest不会将每个图表强制为be重新更新。在封面下,这将保存所有三个调用的最新值。例如,A1、B1和C1。如果B1更新为B2,下一个值将是A1、B2、C1。请注意A和C引用没有更改。因此,它与您的答案相同。但更优雅的是AFAIAC,因为您不需要在之后清理订阅。您是对的关于
async
我没有注意到。但是,它必须一次更新所有图表,而不是像您描述的那样,因为每次更改
图形时,|async
都会收到一个新数组,然后它会再次销毁并重新创建所有三个
元素。但是您的解决方案肯定比我的更简单底图组件将检查参考:)。或者它将在阵列上循环,并将changeDetection strategy设置为onPush的子组件。我希望我可以将这两个组件都标记为答案,因为它们都以不同的方法解决问题。另一个答案更接近我现有的方法,也是我采用的方法,但是这个答案也帮助我完成了CombineTest函数,并进一步理解了异步管道。谢谢你的回答,谢谢你的回答。这两个答案都有效,但这更接近我一直在尝试的,对我现有的方法造成的改变最少。