Angular:如何访问$timeout callback之外的参数



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

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()

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

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

解决方案

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

相关内容

  • 没有找到相关文章

最新更新