与angular-nvd3一起使用的nvd3是slooooowwwww

cir*_*sio 2 javascript angularjs nvd3.js angular-nvd3

我相信我有一个问题可以通过我缺少的东西很容易解决,但我似乎无法看到实际问题是什么.我有一个应用程序每秒返回5000点(5个数组元素1000 x,y点),我想在客户端使用NVD3更新.这是一个AngularJS应用程序,所以我使用的是krispos angular-nvd3指令.然而,它正在淹没整个应用程序,看起来,根据Chrome开发人员工具捕获的时间线,应用程序似乎正在等待d3_timer_step返回5-6秒.

我认为这个问题是由于我们如何更新数据,但整个问题似乎与实际的d3部分有关.客户端的代码是

<nvd3 options="optionsRingdown" data="ringdownAvg" config="{refreshDataOnly:true}"></nvd3>
Run Code Online (Sandbox Code Playgroud)

在控制器中,选项定义如下

$scope.options = {
    chart: {
      type: 'lineChart',
      height: 300,
      margin: {
        top: 20,
        right: 40,
        bottom: 60,
        left: 75
      },
      x: function(d) {
        return d.x;
      },
      y: function(d) {
        return d.y;
      },
      useInteractiveGuideline: false,
      yAxis: {
        tickFormat: function(d) {
          return d3.format('0.01f')(d);
        },
        axisLabel: 'Testing'
      },
      xAxis: {
        tickFormat: function(d) {
          return d3.time.format('%X')(new Date(d));
        },
        rotateLabels: -45
      },
      transitionDuration: 0,
      showXAxis: true,
      showYAxis: true
    }
  };
Run Code Online (Sandbox Code Playgroud)

并且数据在以下模板中定义

var ringdownT = [{
   values: [],
   key: 'Cell 0'
 }, {
   values: [],
   key: 'Cell 1'
 }, {
   values: [],
   key: 'Cell 2'
 }, {
   values: [],
   key: 'Cell 3'
 }, {
   values: [],
   key: 'Cell 4'
 }];
Run Code Online (Sandbox Code Playgroud)

使用以下内容通过服务广播上的函数调用更新数据

function updateCRD(d){
   var dataOut = {
     "tauData": [],
     "rdFit": ringdownT,
     "rdAvg":ringdownT
   }
   for (k = 0; k < d.cell.length; k++) {
     dataOut.rdAvg[k].values = d.cell[k].avg_rd;
     dataOut.rdFit[k].values = d.cell[k].fit_rd;
   }

   return dataOut;
}
Run Code Online (Sandbox Code Playgroud)

使用以下内容在广播中调用该函数(以1秒间隔广播)

$scope.$on('dataAvailable', function() {

    $scope.data = Data.crd;

    var data = updateCRD(Data.crd);

    $scope.tauData = data.tauData;
    $scope.ringdownAvg = data.rdAvg;
    $scope.ringdownFit = data.rdFit;
});
Run Code Online (Sandbox Code Playgroud)

有没有人看到这里看起来很明显错误的东西,或者我应该采取不同的做法?有没有我错过的选项?任何帮助都会很棒.

干杯,马特

kri*_*spo 7

尝试将deepWatchData: false标志添加到配置(这意味着该指令不会监视更新的数据)并通过api以下方式更新图表:

<nvd3 options="optionsRingdown" data="ringdownAvg" api="apiRingdown" config="{refreshDataOnly:true, deepWatchData: false}"></nvd3>
Run Code Online (Sandbox Code Playgroud)

该指令使用$watch(watchExpression, listener, [objectEquality])方法监视任何更新的选项和复杂数据对象.在我们的例子中deepWatchDataobjectEquality标志,同时观看图表数据的更新.

根据角度文档,watchExpression的不等式是根据angular.equals函数确定的.为了保存对象的值以供以后比较,使用angular.copy函数.因此,这意味着观看复杂对象将产生不利的记忆和性能影响.

仅在版本(1.0.2,1.0.3)中,此标志false默认为.


然后,要更新图表,我们可以apiRingdown.update在您的控制器中使用方法:

$scope.$on('dataAvailable', function() {

    $scope.data = Data.crd;

    var data = updateCRD(Data.crd);

    $scope.tauData = data.tauData;
    $scope.ringdownAvg = data.rdAvg;
    $scope.ringdownFit = data.rdFit;

    //this line updates the chart
    $scope.apiRingdown.update();
});
Run Code Online (Sandbox Code Playgroud)

更新

最新版本[1.0.4+]中添加了一些更新.现在标志deepWatchData意味着使用或不使用数据(它不像objectEquality以前那样).而且deepWatchDatatrue默认.但现在我们可以$watch通过新的旗帜来管理深度deepWatchDataDepth: 2,从而调节性能.使用此标志,我们可以为数据指定更改检测策略(范围$ watch depth):

0 - By Reference (the least powerful, but the most efficient)
1 - By Collection Items
2 - By Value (the most powerful, but also the most expensive; default value)
Run Code Online (Sandbox Code Playgroud)

此外,标志refreshDataOnlytrue默认情况下.

因此,更新的标记元素可能如下所示:

<nvd3 options="optionsRingdown" data="ringdownAvg" api="apiRingdown" config="{deepWatchDataDepth: 0}"></nvd3>
Run Code Online (Sandbox Code Playgroud)

演示