$ scope.watch不会等到变量发生变化

时间:2015-11-30 21:50:43

标签: javascript angularjs

我的控制器中有这个代码:

$scope.$watch(userService.getUser, function(getUser){
          console.log(getUser);
          var user = getUser;

这在我的服务中:

.service('userService', function ($http, $q, auth, userFactory) {
        var user;

        userFactory.getUser2(auth.currentUser()).getValue(function(result){
            //console.log(result);
            user = result;
        });

        this.getUser = function() {
            //console.log(user);
            return user;
        }

    })

代码可以工作,但是我得到错误,因为我的控制器代码是在用户变量更改之前执行的。我应该与承诺合作,我试过这个但是没有完全正常工作。

这是我在userFactory中的API调用:

userFactory.getUser2 = function(usr){
      return{
        getValue: function(callback){
          $http({
            method: 'POST',
            url:'http://groep6api.herokuapp.com/user',
            headers: {'Content-Type': 'application/x-www-form-urlencoded'
            //'authentication': 'bearer' + $window.localStorage.getItem('eva-token')
            },
            transformRequest: function(obj) {
              var str = [];
              for(var p in obj)
                str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
              return str.join("&");
            },
            data : {username: usr}
          }).success(function (result) {
            //console.log("userfactory getUser:", result[0]);
            callback(result[0]);
          });
        }
      }
    };

只有$ scope.watch可以实现吗?或者我应该使用承诺,如果是这样,在这种情况下实施承诺的正确方法是什么?我试用了$ q等等,但这只是给出了一系列其他错误。

3 个答案:

答案 0 :(得分:1)

您需要添加一个防护(if),以防止在您的异步调用完成之前执行其余的控制器代码,或者只是将其余的控制器代码放入其中$scope.$watch回调:

$scope.$watch(userService.getUser, function(getUser){
  var user = getUser;

  // do the rest of your stuff
});

或类似的东西:

$scope.user = null;

$scope.$watch(userService.getUser, function(getUser) {
  $scope.user = getUser;
});

if($scope.user) {
  // do the rest of your stuff
}

在第二个示例中,需要使用$scope.user(或附加到$scope的内容),以便触发摘要周期并重新评估if后卫。

答案 1 :(得分:0)

所以这就是我通常处理这种情况的方式。

首先,我只有一个处理$ http请求的工厂。我返回$ http,它有内置的承诺。这样就可以避免添加任何手表和任何异步问题。

所以我的工厂看起来像这样:

userFactory = function($http){
    return{
        getUser: function(usr){
            return $http({
                method: 'POST',
                url:'http://groep6api.herokuapp.com/user',
                headers: {'Content-Type': 'application/x-www-form-urlencoded'},
                transformRequest: function(obj) {
                    var str = [];
                    for(var p in obj)
                        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
                    return str.join("&");
                },
                data : {username: usr}
            });
        }
    };
}

在你的控制器中你会这样做:

userFactory.getUser('bob').success(function(response){
    $scope.user = response;
});

以下是如何将用户数据保存在var中。每次调用getUser时,它都会检查var是否为null,如果它为null则发出请求,如果不是则返回该var。

userFactory = function($http, $q){
    var user = null;

    return{
        getUser: function(usr){
            return $q(function (resolve, reject) {
                if(user) resolve(user);

                else{
                    $http({
                        method: 'POST',
                        url:'http://groep6api.herokuapp.com/user',
                        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
                        transformRequest: function(obj) {
                            var str = [];
                            for(var p in obj)
                                str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
                            return str.join("&");
                        },
                        data : {username: usr}
                    })
                    .then(function(response){
                        user = response;
                        resolve(user);
                    });
                }
            });
        }
    };
}

答案 2 :(得分:0)

您可以使用$watch,尤其是您正在聆听模型中的价值变化。如果要提供该函数,它应返回一个将在$digest周期内作出反应的值,而不是执行Ajax请求或$http函数的函数。

在您的示例中,您应该观看分配给范围内的模型的返回值,并使用$digest函数处理所有观察者或$apply如果您是从指令调用它。