【问题标题】:Angular performance issues, ng-repeat, unwanted callbacks角度性能问题、ng-repeat、不需要的回调
【发布时间】:2015-07-15 22:09:53
【问题描述】:

我的 Angular 应用程序面临一些严重的性能问题,这肯定是由于我的 ng-repeat 实施不当,但我不知道如何做得更好。我尝试了其他一些组合,但都没有给我想要的结果,也没有更好的性能。由于异步和 $digest 中止,出现了一些无限循环、未定义的变量。 这就是它应该看起来的样子(所以这是工作结果,但目前还没有优化):http://scr.hu/0ei9/8bpw9

蓝色单元格的天数 = 用户在场,红色单元格 = 不存在。下面是每天的“班次”(每个班次可以在不同的日子完成)。

当我 console.log 一些函数时,它们被调用的次数超出了需要的次数,例如 isPresent(用于检查用户是否提交了可用的日期)被称为 5x180(180可能是 5 个用户 x 每月 30 天)和 getDayOfWeek(在班次行的模板中使用)28+840+812...有 10 个班次。

而我通常只需要为所有单元格调用 isPresent 1x180 并为一个班次行调用一个月中的 1x30 天 getDayOfWeek。也就是说,我真的不明白为什么它被调用了这么多次以及如何优化它。

此外,当我单击蓝色单元格时,会调用 setShift() 函数。我在这里复制了函数但不分析它,我只是想表明它没有调用任何以前的函数,但是我 console.log 令人印象深刻的 28x“星期几”+ 180“存在”和 + 812 “一周中的天”。不知道它来自哪里...坦率地说,我单击的所有内容都称为相同的数量-如果我更改月份,年份,请单击一个独立的按钮...

为了更好地阅读代码,我省略了一些类和 css。

感谢您的帮助。

编辑

在注释和取消注释一些代码之后,我发现当我调用 setShift() 函数时,大多数不需要的日志来自最后一个子调用:showPopover(),我在其中打开了一个 $modal。评论时,我看到的只有 1/3。在模态出现之前,剩下的就是这些东西了。此外,我认为 templpateUrl 可能是原因,因为在评论时它没有记录所有数百个“存在”和“星期几”。当我单击模式上的任意位置时,它会调用所有这些功能。有任何想法吗?

JS 角度函数

            $scope.isPresent = function(day, month, year, userId) {
              console.log('is present')
              var date = new Date(year, month - 1, day + 1)
              var day = moment(date).format("D-M-YYYY");
              for (var i = 0; i < $scope.presences.length; i++) {
                var presentDay = moment($scope.presences[i].start).format("D-M-YYYY")
                if (presentDay == day && userId == $scope.presences[i].coursierId) {
                  return true
                }
              }
            }

            $scope.getDayOfWeek = function(day, month, year) {
                console.log('day of the week')
                var date = new Date(parseInt(year), month - 1, day + 1)
                var dayId = date.getDay();
                return dayId;
              }
              /*
                used for a limited ng-repeat
              */
            $scope.getTimes = function(n) {
              return new Array(n);
            };


            /*
              Shows a list of sorted out shifts with corresponding
              hours, cities and capabilities of coursier.
            */
            $scope.setShift = function(day, month, year, userId, event) {
              var date = new Date(year, month - 1, day)
              var day = moment(date).format("D-M-YYYY");
              var dayOfWeek = moment(date).day()
                //SORT SHIFTs BY DAY OF WEEK clicked
              var day_shifts = $scope.sortShiftByDayOfWeek(dayOfWeek)
                //console.log(day_shifts)
                //check if the day clicked is an dispo present day
              for (var i = 0; i < $scope.presences.length; i++) {
                var dispoDay = moment($scope.presences[i].start).format("D-M-YYYY")
                  //if yes, check the presence user id and the cell of user clicked
                if (dispoDay == day) {
                  //then get all the shifts that fit into this coursier's time range
                  if ($scope.presences[i].coursierId == userId) {
                    var dispo = $scope.presences[i];
                    var dispoHours = $scope.getDispoHoursAndDay(dispo);
                    var time_shifts = $scope.compareDiposHoursAndShift(dispoHours, day_shifts);
                    //then sort the shifts by the dispo's and shift's cities
                    var time_city_shifts = $scope.compareDispoCityAndShift(time_shifts, dispo);
                    var time_city_able_shifts = $scope.compareUserAndShift(time_city_shifts, userId);
                    $scope.showPopover(time_city_able_shifts, event);
                  }
                };
              };
            }
###Calendar table
<table class="table table-bordered">
  <!--days of month-->
  <tr class="mainHeader">
    <th>coursier/jour</th>
    ##calendar.days = 30 days of month, for example
    <th class="monthDay" ng-repeat=" numDay in [] | range: calendar.days">{{$index+1}} {{calendar.daysNames[$index]}}
    </th>
  </tr>

  <!-- user name and days -->
  <tr ng-repeat="user in coursiers">
    <!-- <td class="coursierName">nom coursier</td> -->
    <td>
      <a href="#"> {{user.name}}</a> 
    </td>
    <td ng-click="setShift($index+1, monthNum,year, user._id, $event)" ng-repeat="numDay in getTimes(calendar.days) track by $index" ng-class=" isPresent($index, monthNum,year, user._id) == true ?   
           'present' : isAbsent($index, monthNum,year, user._id) == true ?  
           'absent' : '' ">
    </td>
  </tr>

  <tr>
    <td>Shifts par jour</td>
    <td class="shiftsParJourCell" ng-repeat="day in getTimes(calendar.days) track by $index">
      <span ng-repeat="shift in shifts">
                <span ng-repeat="jour in shift.jours">
                  {{jour.id == 
                    getDayOfWeek($parent.$parent.$index, monthNum, year) ? shift.nom : ''}}
                </span>
      </span>
    </td>
  </tr>
</table>

【问题讨论】:

  • 我会首先在每次视图更改时对视图数据进行预处理,而不是在摘要周期中处理它,从而尽可能多地消除 ng-repeat 中的函数调用。
  • 看看this question and its answer。您的视图可能会被多次评估以确认它没有更改,这就是您看到这么多函数调用的原因。根据 Kevin B 的建议,尝试使用直接更新数据的观察者来摆脱方法调用。
  • 另外,@ginold,如果你能创建一个 Plunker/jsFiddle,我们或许能提供更好的帮助。没有工作示例就很难优化代码。
  • 在 ng-repeat 上使用一次性绑定表达式 ::getTimes(calendar.days),在插值上使用 {{::,以减少调用(角度 1.3+)
  • 在注释和取消注释一些代码之后,我发现当我调用 setShift() 函数时,大部分不需要的日志来自最后一个子调用:showPopover() 我打开 $modal .评论时,我看到的只有 1/3。在模态出现之前,剩下的就是这些东西了。此外,我认为 templpateUrl 可能是原因,因为在评论时它没有记录所有数百个“存在”和“星期几”。当我单击模式上的任意位置时,它会调用所有这些功能。有什么想法吗?

标签: javascript angularjs performance optimization ng-repeat


【解决方案1】:

过了一会儿,我的问题是我没有使用指令。 范围有不必要的交互(仍然不知道为什么),但是在角度指令中分离我的 html 后,到目前为止没有任何问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-04
    • 2016-04-23
    • 2014-05-21
    • 2015-01-15
    • 1970-01-01
    • 2016-08-14
    • 1970-01-01
    相关资源
    最近更新 更多