0

我有一个小型 AngularJS 应用程序,它使用 JSON 和 UTC 时间格式从服务器带回用户列表和他们的下一次预定会议(假设在接下来的 8 小时内安排),以便于计算到本地时间. 每个用户可能有不同的状态(忙到 x 时间,空闲直到 x 时间)。

我想要完成的是能够在预定会议完成之前的剩余时间或会议开始之前的剩余时间更新 DOM。我有一些代码可以工作,但是因为我显然没有正确执行此操作,结果集中只有几个条目,它使浏览器几乎停滞不前。任何建议,将不胜感激!

我当前的代码由以下片段组成:

[主页]

<tr ng-repeat="item in pagedItems[currentPage-1] | orderBy:sortingOrder:reverse" ng-class="{success:item._freeBusy=='Free', error:item._freeBusy=='Busy'}">
       <td>{{item._firstName}}</td>
       <td>{{item._lastName}}</td>
       <td>{{item._facilityName}}</td>
       <td>{{item._extension}}</td>
       <td>{{item._description}}</td>
       <td><a ng-hide="!item._extension" ng-click="dial(item)">Dial</a></td>
       <td><button class="btn btn-primary" ng-click="openDetails(item)">Details</button></td>
       <td>{{item._freeBusy}} {{item._timeLeft}} {{calculateTime(item._freeBusyTime,$index)}}</td>
 </tr>

[控制器]

        $scope.timeUntil = function(s) {
        function isoToObj(s) {
            var b = s.split(/[-T+:]/i);
            return new Date(Date.UTC(b[0], --b[1], b[2], b[3], b[4], b[5]));
        }
        // Utility to add leading zero
        function z(n) {
            return (n < 10 ? '0' : '') + n;
        }
        // Convert string to date object
        var d = isoToObj(s);
        var diff = d - new Date();
        // Allow for previous times
        var sign = diff < 0 ? '-' : '';
        diff = Math.abs(diff);
        // Get time components
        var hours = diff / 3.6e6 | 0;
        var mins = diff % 3.6e6 / 6e4 | 0;
        var secs = Math.round(diff % 6e4 / 1e3);
        // Return formatted string
        return sign + z(hours) + ' Hours ' + z(mins) + ' Min' + ':' + z(secs);// + ':' + z(secs)
    }

    $scope.calculateTime = function(s, idx) {
        timeoutID = $timeout(function() {
            $scope.items[idx]._timeLeft = $scope.timeUntil(s);
            $scope.calculateTime(s, idx);
        }, 1000);
    };

编辑

我了解下面提到的问题,我正在努力解决的是如何正确注册。因为它可能有多达 15 次以上的单独时间更新到我迷路的单个滴答声。

4

3 回答 3

1

您注册的超时时间比您想象的要多。每次 Angular 呈现您的视图时,您都会注册新的超时处理程序。添加回调的计数器并观察计数:

$scope.called = 0;

$scope.calculateTime = function(s, idx) {
    timeoutID = $timeout(function() {
        $scope.items[idx]._timeLeft = $scope.timeUntil(s);
        $scope.calculateTime(s, idx);
        console.log(++$scope.called);
    }, 1000);
};

请参阅我复制错误的地方:http: //plnkr.co/edit/qJ4zDl6gc5C7Edg0T0gB。只需运行它并观察计数器。

为什么要在渲染周期中更新 _timeLeft?为什么不这样做:

$scope.called = 0;

setInterval(function() {
  angular.forEach($scope.items, function function_name(item) {
    item._timeLeft = $scope.timeUntil(item._freeBusyTime);
  });
  console.log(++$scope.called);
  $scope.$apply();
}, 1000);

查看新的 plunk:http://plnkr.co/edit/rVJ6p4VXDQvt7rjT6eka

于 2013-04-25T01:08:09.030 回答
1

您正在递归调用 $scope.calculateTime!而且您正在 ng-repeat 期间修改项目列表,这也会导致无限循环。

这个怎么样:http ://plnkr.co/edit/0JqK96irV4ETdWZYxO3P?p=preview

将 html 更改为引用不影响 ng-repeat 的单独数组:

<td>in {{_timeLeft[$index]}}</td>

更新如下:

$scope._timeLeft = [];

var intervalID = window.setInterval(function() {
    for (var i=0; i<$scope.items.length; i++) {
      $scope._timeLeft[i] = $scope.timeUntil($scope.items[i]._freeBusyTime);
    }
    $scope.$apply();
}, 1000);

请注意,$scope.$apply() 需要让 Angular 知道 '_timeLeft' 已被修改,这会更新对它的所有引用。

于 2013-04-25T01:10:56.747 回答
0

我认为您不应该调用$timeout每个视图更新。相反,您可以在控制器中倒计时并让视图显示计时器。

http://plnkr.co/edit/OUVdJyllzmVmPC0FhqYF?p=preview

于 2013-04-25T00:29:41.317 回答