所有$ watch执行后的AngularJS控制器事件

时间:2015-04-06 13:28:03

标签: javascript angularjs coffeescript watch

在所有控制器匹配器执行后,可以触发一个事件(只有一次)?

例如:

$scope.$watch 'var1', (value) ->
  # Do something ...
  callEvent()

$scope.$watch 'var2', (value) ->
  # Do something ...
  callEvent()

$scope.$watch 'var3', (value) ->
  # Do something ...
  callEvent()

$scope.$watch 'var4', (value) ->
  # Do something ...
  callEvent()

在我的情况下,callEvent()被激活4次,但我只需要一次。

我也可以更改我的业务应用逻辑,但这将是非常长期的。

4 个答案:

答案 0 :(得分:1)

一种方法是使用额外的深度监视(不知道CS,代码将在JS中):

$scope.$watch(
    function() {
        return {
            var1: $scope.var1,
            var2: $scope.var2,
            var3: $scope.var3,
            var4: $scope.var4
        };
    },
    function(newval) {
        callEvent();
    },
    true // deep watch
);

请注意,每个摘要周期将再次触发一次事件!

另一种方法是使用一个标志 - 它需要用超时重置(丑陋):

var flag = false;

$scope.$watch('var1', function(newval) {
    // Do something
    callEventOnce();
});

// same for var2, 3, 4

function callEventOnce() {
    if( !flag ) {
        flag = true;
        $timeout(function() {
            flag = false;
        });
        callEvent();
    }
}

逃避超时丑陋的一种方法是让控制器监听事件然后重置标志。例如,如果callEvent()实现为:

// HYPOTHETICAL IMPLEMENTATION OF callEvent()
function callEvent() {
    $rootScope.$broadcast('my_event');
}

将其添加到控制器:

$scope.$on('my_event', function() {
    flag = false;
});

答案 1 :(得分:1)

如何使用Promise?

watchNames = 'var1 var2 var3 var4'.split(' ')
watchDefers = {}

eventHandler = ->
  # do what you want

  initDefers()

initDefers = ->
  watchNames.forEach (varName) ->
    watchDefers[varName] = $q.defer()

  watchPromiseArray = watchNames.map (varName) ->
    watchDefers[varName].promise

  $q.all(watchPromiseArray).then eventHandler

$scope.$watch 'var1', (value) ->
  watchDefers.var1.resolve()

$scope.$watch 'var2', (value) ->
  watchDefers.var2.resolve()

$scope.$watch 'var3', (value) ->
  watchDefers.var3.resolve()

$scope.$watch 'var4', (value) ->
  watchDefers.var4.reolsve()

initDefers()

答案 2 :(得分:0)

您的watchExpression绑定了var*个字符串;你需要添加(例如boolean),所以它会像你的var*boolean;成功执行后更改boolean值。

另一种方法是更改​​watchExpression itselft,但这有点棘手且模糊;另一个可能是取消绑定你的$watch听众。

祝你好运,如果您碰巧有更好/不同的方法,请告诉我。

答案 3 :(得分:0)

您可以使用$watchGroup

$scope.$watchGroup(['var1', 'var2', 'var3', 'var4'], function(newVal, oldVal) {
    // your code here
});

参考:https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope http://www.dotnettricks.com/learn/angularjs/understanding-watch-watchgroup-and-watchcollection-methods-of-scope