Angular:如何访问$ timeout回调之外的参数?

时间:2014-07-24 22:48:22

标签: javascript angularjs timeout

我有一个像这样的超时循环:

var somedata = {
        autoRefreshInterval: 300,
        autoRefreshInSec: 300,
        myTimeout: null,
        doRefresh: _doRefresh,
        onTimeout: function () {
            this.autoRefreshInSec--;
            if (this.autoRefreshInSec <= 0) {
                this.autoRefreshInSec = this.autoRefreshInterval; 
                this.doRefresh();
            }
            this.myTimeout = $timeout(this.onTimeout, 1000);
        },
        startTimer: function () {
            this.autoRefreshInSec = this.autoRefreshInterval;
            this.myTimeout = $timeout(this.onTimeout, 1000);
        },
        stopTimer: function () {
            $timeout.cancel(this.myTimeout);
        },
    }

似乎&#34;这个&#34;不在onTimeout回调函数内部工作,而它适用于startTimer和stopTimer。如何解决?

更新:

由于根据下面的答案之一在onTimeout中丢失了,我尝试将其传递到这样:

onTimeout: function (self) {
    self.autoRefreshInSec--;
    if (self.autoRefreshInSec <= 0) {
        self.autoRefreshInSec = self.autoRefreshInterval;  // Set it here so that it does't start refresh right away. It will be reset when refresh is done.
        self.doRefresh();
    }
    self.myTimeout = $timeout(self.onTimeout(self), 1000);
},
startTimer: function () {
    this.autoRefreshInSec = this.autoRefreshInterval;
    this.myTimeout = $timeout(this.onTimeout(this), 1000);
},

奇怪的是,当我通过代码调试时,它看起来很有效。但是,一旦我删除了断点,就会连续触发self.doRefresh()。为什么呢?

更新2:

好的,我在http://jsfiddle.net/qY86q/1创建了一个JSFiddle来说明问题。

2 个答案:

答案 0 :(得分:2)

Function.prototype.bind()

  

bind()方法创建一个新函数,在调用时,将其this关键字设置为提供的值,并在调用新函数时提供任何前面提供的给定参数序列。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

您案件的解决方案

&#13;
&#13;
angular.module('myApp', [])
  .service('timerService', function($timeout) {
    var _timer = {
      autoRefreshInterval: 300,
      autoRefreshInSec: 300,
      myTimeout: null,
      onTimeout: function() {
        this.autoRefreshInSec -= 1;
        if (this.autoRefreshInSec <= 0) {
          this.autoRefreshInSec = this.autoRefreshInterval;
          console.log('refreshing');
        }
        console.log('time: ', this.autoRefreshInSec);
        this.myTimeout = $timeout(this.onTimeout.bind(this), 1000);
      },
      startTimer: function() {
        if (this.myTimeout) {
          this.stopTimer(this.myTimeout)
        }
        this.autoRefreshInSec = this.autoRefreshInterval;
        this.myTimeout = $timeout(this.onTimeout.bind(this), 1000);
      },
      stopTimer: $timeout.cancel // see note(1)
    };
    var context = {
      timer: _timer
    };
    return context;
  }).controller('PrefsCtrl', function PrefsCtrl($scope, timerService) {
    $scope.timer = timerService.timer;
  })
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp">
  <div ng-controller="PrefsCtrl">
    <button ng-click="timer.startTimer()">Click to Start or Reset Timer</button>
    <div>{{timer.autoRefreshInSec}}</div>
  </div>
</div>
&#13;
&#13;
&#13;

注意(1),这是

的缩影
stopTimer: function(timer) {
   $timeout.cancel(timer)
}

答案 1 :(得分:0)

这是一个javascript绑定问题。

尝试:

var somedata;  // now this can be referenced in the angular.bind call
somedata = {
    onTimeout: angular.bind(somedata, function () {
        this.autoRefreshInSec--;
        if (this.autoRefreshInSec <= 0) {
            this.autoRefreshInSec = this.autoRefreshInterval; 
            this.doRefresh();
        }
        this.myTimeout = $timeout(this.onTimeout, 1000);
    })
}

这将确保在调用函数时this是&#34;绑定&#34;回调中的somedata