我有一个这样的超时循环:
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);
},
}
看来,"this"不工作内部的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来说明这个问题。
Function.prototype.bind()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bindbind()方法创建一个新函数,当调用该函数时,将其this关键字设置为所提供的值,并在调用新函数时提供的任何参数之前设置给定的参数序列。
解决方案
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;
})
<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>
注释(1),这是
的快捷方式stopTimer: function(timer) {
$timeout.cancel(timer)
}
这是一个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
在回调中被"绑定"到somedata
。