【问题标题】:using setInterval in angularjs factory在 angularjs 工厂中使用 setInterval
【发布时间】:2012-12-23 14:37:45
【问题描述】:

我正在尝试 angularjs 文档中给出的代码(此处给出:http://jsfiddle.net/zGqB8/) 它只是实现了一个时间工厂,并使用 $timeout 在每一秒之后更新时间对象。

angular.module('timeApp', [])
.factory('time', function($timeout) {
    var time = {};

    (function tick () {
        time.now = new Date().toString();
        $timeout(tick, 1000);  // how to do it using setInterval() ?
    })();

    return time;
});

我将如何使用 setInterval() 函数而不是 $timeout() 来做到这一点? 我知道需要使用scope.$apply() 来进入角度执行上下文,但是在工厂函数中这将如何工作?我的意思是,在控制器中,我们有一个作用域,但我们在工厂函数中没有作用域?

【问题讨论】:

  • 为什么需要使用setInterval?这达到了相同的结果。
  • 我喜欢你目前的解决方案。
  • @LiviuT。是的,它在这里工作,但我只是想知道在工厂函数中如何进入角度执行上下文。
  • Angular 现在有 $interval: docs.angularjs.org/api/ng/service/$interval

标签: javascript angularjs javascript-framework


【解决方案1】:

您可以使用$timeout 作为间隔。

var myIntervalFunction = function() {
    cancelRefresh = $timeout(function myFunction() {
        // do something
        cancelRefresh = $timeout(myIntervalFunction, 60000);
    },60000);
};

如果视图被销毁,你可以通过监听$destroy来销毁它:

$scope.$on('$destroy', function(e) {
        $timeout.cancel(cancelRefresh);
});

【讨论】:

  • 我猜你误解了这个问题。 JS的setInterval()函数重复调用一个函数。
  • 我知道。目前在 Angular 中没有 setInterval 替代方案。模拟它的唯一方法是递归调用自身的 $timeout 函数。
  • 让我们看看在我开始收到 stackoverflow 异常之前它会持续多久
  • @LeblancMeneses:这里没有递归,所以不会有任何堆栈溢出。
  • @TylerForsy 你是对的,我已经恢复了一个错误地将myFunction 重命名为myIntervalFunction 的更改。但是,堆栈溢出没有问题,因为每个 $timeout 不是递归调用,而是延迟执行提供的函数,该函数将使用新的调用堆栈执行。
【解决方案2】:

更新

Angular 在 1.2 版中实现了 $interval 功能 - http://docs.angularjs.org/api/ng.$interval


下面的旧示例,除非您使用的是早于 1.2 的版本,否则请忽略。

Angular 中的 setInterval 实现 -

我创建了一个名为 timeFunctions 的工厂,它公开了 $setInterval 和 $clearInterval。

请注意,每当我需要在工厂中修改范围时,我都会将其传入。我不确定这是否符合“Angular 方式”的做事方式,但效果很好。

app.factory('timeFunctions', [

  "$timeout",

  function timeFunctions($timeout) {
    var _intervals = {}, _intervalUID = 1;

    return {

      $setInterval: function(operation, interval, $scope) {
        var _internalId = _intervalUID++;

        _intervals[ _internalId ] = $timeout(function intervalOperation(){
            operation( $scope || undefined );
            _intervals[ _internalId ] = $timeout(intervalOperation, interval);
        }, interval);

        return _internalId;
      },

      $clearInterval: function(id) {
        return $timeout.cancel( _intervals[ id ] );
      }
    }
  }
]);

示例用法:

app.controller('myController', [

  '$scope', 'timeFunctions',

  function myController($scope, timeFunctions) {

    $scope.startFeature = function() {

      // scrollTimeout will store the unique ID for the $setInterval instance
      return $scope.scrollTimeout = timeFunctions.$setInterval(scroll, 5000, $scope);

      // Function called on interval with scope available
      function scroll($scope) {
        console.log('scroll', $scope);
        $scope.currentPage++;

      }
    },

    $scope.stopFeature = function() {
      return timeFunctions.$clearInterval( $scope.scrollTimeout );
    }

  }
]);

【讨论】:

    【解决方案3】:

    您能否调用一个普通的 JavaScript 方法,然后在该方法中用 $apply 包装 Angular 代码?

    示例

    timer = setInterval('Repeater()', 50);
    
    var Repeater = function () {
      // Get Angular scope from a known DOM element
      var scope = angular.element(document.getElementById(elem)).scope();
      scope.$apply(function () {
        scope.SomeOtherFunction();
      });
    };
    

    【讨论】:

      【解决方案4】:

      最新的候选版本 (1.2.0 rc3) 支持 interval。见changelog

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-24
        • 1970-01-01
        • 2014-06-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多