更新「;“很久以前”;以Angularjs和Momentjs表示的值

更新「;“很久以前”;以Angularjs和Momentjs表示的值,angularjs,momentjs,Angularjs,Momentjs,原始:我有一个使用ng repeat生成的表,其中有数百个条目,由几个不同的unix时间戳组成。我正在使用moment.js使它们显示为“19分钟前”或是无论它是多久以前。例如,我如何每五分钟更新一次这些数据,而不必刷新整个表(这需要几秒钟的时间,并且会中断用户的排序和选择)。使用angular的服务(仅是setTimeout())来更新数据。请注意第三个参数,它指示Angular应该运行更新数据绑定的$digest循环 下面是一个例子: (本例每秒钟更新一次,这样您就不必等待5分钟才能看到它;

原始:我有一个使用ng repeat生成的表,其中有数百个条目,由几个不同的unix时间戳组成。我正在使用moment.js使它们显示为“19分钟前”或是无论它是多久以前。例如,我如何每五分钟更新一次这些数据,而不必刷新整个表(这需要几秒钟的时间,并且会中断用户的排序和选择)。

使用angular的服务(仅是
setTimeout()
)来更新数据。请注意第三个参数,它指示Angular应该运行更新数据绑定的
$digest
循环

下面是一个例子:

(本例每秒钟更新一次,这样您就不必等待5分钟才能看到它;-)

我最终拥有$scope.apply(),setInterval每五分钟调用一次,它会重新应用过滤器,将时间戳格式化为“x分钟前”。也许有点老套,但很管用。我敢肯定这不是最佳解决方案。

我相信,因此使用过滤器显示“时间前”字符串可能会因为数百个条目而导致CPU开销增加

我决定采用pubsub体系结构,使用基本建议的方法(主要是因为我不必监视
$destroy
事件并手动取消订阅),但使用NotificationService而不是“Channel”功能:

.factory('NotificationService', ['$rootScope',
function($rootScope) {
    // events:
    var TIME_AGO_TICK = "e:timeAgo";
    var timeAgoTick = function() {
        $rootScope.$broadcast(TIME_AGO_TICK);
    }
    // every minute, publish/$broadcast a TIME_AGO_TICK event
    setInterval(function() {
       timeAgoTick();
       $rootScope.$apply();
    }, 1000 * 60);
    return {
        // publish
        timeAgoTick: timeAgoTick,
        // subscribe
        onTimeAgo: function($scope, handler) {
            $scope.$on(TIME_AGO_TICK, function() {
                handler();
            });
        }
    };
}])
time ago
指令使用NotificationService注册/订阅时间戳(
post.dt
,在下面的示例HTML中):

<span time-ago="post.dt" class="time-ago"></span>

.directive('timeAgo',['NotificationService',
功能(通知服务){
返回{
模板:“{timeAgo}}”,
替换:正确,
链接:函数(范围、元素、属性){
var updateTime=function(){
scope.timeAgo=moment(scope.$eval(attrs.timeAgo)).fromNow();
}
NotificationService.onTimeAgo(作用域,更新时间);//订阅
updateTime();
}
}
}])
几点意见:

  • 我试图提高效率,而不是让指令创建一个新的范围。尽管该指令向作用域中添加了
    timeAgo
    属性,但在我的使用中,这是可以的,因为我似乎只在ng repeat中使用
    timeAgo
    指令,所以我只是将该属性添加到ng repeat创建的子作用域中
  • {{timeAgo}}
    将在每个摘要周期进行检查,但这应该比运行筛选器更快
  • 我也喜欢这种方法,因为我没有在每个时间戳上运行计时器。我有一个计时器在NotificationService中运行
  • 函数
    timeAgoTick()
    可以设置为私有,因为可能只有NotificationService需要发布时间间隔事件

    • 我为momentjs做了一个包装

      {{“2014-05-21T14:25:00Z”{momentFromNow}


      我希望它对您有用。

      我使用以下过滤器。过滤器每60秒更新一次值

      angular
        .module('myApp')
        .filter('timeAgo', ['$interval', function ($interval){
          // trigger digest every 60 seconds
          $interval(function (){}, 60000);
      
          function fromNowFilter(time){
            return moment(time).fromNow();
          }
      
          fromNowFilter.$stateful = true;
          return fromNowFilter;
        }]);
      
      和html格式

      <span>{{ myObject.created | timeAgo }}</span>
      
      {{myObject.created | timeAgo}
      
      我将花一些时间将其应用到我的实现中。从我的观察来看,我当前的实现并不是CPU密集型的,我认为整个页面只有一个计时器,因为这一个计时器调用应用程序,但我相信这样会更好。谢谢你。@CorbinLewis,对不起,我不清楚多重计时器。。。我正在考虑另一种实现,其中可能有人在指令中使用$timeout——这将导致每个时间戳都有一个单独的计时器。我同意你的实现只有一个计时器。你的链接是正确的,但是链接文本上写着“$timeout”。注意,angular还提供了重复调用函数的功能。
      angular
        .module('myApp')
        .filter('timeAgo', ['$interval', function ($interval){
          // trigger digest every 60 seconds
          $interval(function (){}, 60000);
      
          function fromNowFilter(time){
            return moment(time).fromNow();
          }
      
          fromNowFilter.$stateful = true;
          return fromNowFilter;
        }]);
      
      <span>{{ myObject.created | timeAgo }}</span>