【问题标题】:Having an Angular $interval running independent of controller让 Angular $interval 独立于控制器运行
【发布时间】:2016-02-04 02:47:15
【问题描述】:

我在可能的应用程序上有不同的页面,它们有自己的控制器。其中一个有一个 $interval 函数,比如说一个计时器。单击一个按钮将启动此间隔功能,该功能每秒更新一次。我想要的是,我希望能够转到我的应用程序中的任何其他页面(调用不同的控制器),但我希望我的间隔继续运行直到我从第一个控制器明确停止它。 rootScope 区间可以这么说。我该怎么做?

编辑:感谢 Chris 和 Patrick,我现在有了一个简单的服务,如下所示:

  .service('TimerService', function($interval) {
    var promise;
    var timerSeconds = 0;

    this.start = function () {
      promise = $interval(function () {
        timerSeconds++;
      }, 1000);
    };

    this.stop = function () {
      promise.cancel(interval);
      timerSeconds = 0;
    };

    this.getTimer = function() {
      return timerSeconds;
    }
  })

我还将我的当前值 (timerSeconds) 存储在此服务中。但是如何将此值同步到我的控制器?该服务增加 timerSeconds,在我的控制器开始时,我通过它的 getTimer() 函数从该服务中读取它,但它显然不会在我的控制器上更新。 如何将此服务属性与我的本地属性同步?

编辑:

当我将我的服务属性定义为一个对象并将 timerSeconds 定义为该对象内的数字时(似乎原语无法同步):

var timer = {seconds : 0};

this.getTimer = function() {
  return timer;
}

并通过该 getter 从我的控制器获取此对象:

vm.timer = TimerService.getTimer();

它们都是同步的。

【问题讨论】:

    标签: javascript angularjs angularjs-directive angularjs-scope


    【解决方案1】:

    不要费心将它添加到 $rootScope。使用可以在应用程序的任何地方使用的服务。这是一个可以启动和停止的单例计时器。在服务本身中定义 intervalTimeout,或者如果您想真正灵活,请在提供程序中这样做(对于本示例来说可能有点矫枉过正)。

    angular.module('myApp', [])
    
    .service('AppCallback', function ($interval) {
        var states = states = {
            PENDING: 0,
            STARTED: 1
        }, intervalTimeout = 3000, // Set this
        interval;
    
        this.states = states;
      
        this.state = states.PENDING;
        this.start = function (callback) {
            if (this.state !== states.PENDING) {
                return;
            }
    
            interval = $interval(callback, intervalTimeout);
            this.state = states.STARTED;
        }
    
        this.stop = function () {
            if (this.state !== states.STARTED) {
                return;
            }
            $interval.cancel(interval);
            this.state = states.PENDING;
        };
    })
    
    .controller('MainController', function ($scope, AppCallback) {
      var vm = {},
          count = 0;
      
      vm.toggle = function toggle() {
        if (AppCallback.state === AppCallback.states.PENDING) {
          AppCallback.start(function () {
            vm.data = 'Ticked ' + (++count) + ' times.';
          });
         } else {
           AppCallback.stop();
         }
      };
      
      
      $scope.vm = vm;
    });
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <div ng-app="myApp" ng-controller="MainController">
      {{vm.data}}
      <br />
      <button ng-click="vm.toggle()">Toggle</button>
    </div>

    【讨论】:

    • 所以服务正在运行更新控制器中的这个数据对象,但是如果你改变你的控制器并再次调用它会发生什么?您的数据和计数对象将丢失,因为它们是在您的控制器中定义的。 .还是我错过了什么?
    • 我尝试将数据对象添加到 rootScope 并从那里读取。它有点工作,但总是同步 vm 和 rootScope 不是很好你有什么其他建议吗?。
    【解决方案2】:

    如果您想在控制器之间共享任何数据,正确的方法是使用服务。

    然后我会创建一个服务,允许您停止和启动此计时器/间隔。

    最初的控制器会启动它,它会继续“滴答”到永远,直到它停止。

    【讨论】:

    • 我应该在 rootScope 中保留我的计时器对象(将始终按间隔递增的数字)吗?
    • 使用工厂存储该号码。
    • 是的,正如@Rorschach120 建议的那样,将其放在您的服务/工厂中,因为这是您希望在控制器之间共享的一些信息
    猜你喜欢
    • 2016-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-02
    • 1970-01-01
    • 2010-12-17
    相关资源
    最近更新 更多