Angular不更新服务变量

时间:2016-12-03 08:35:15

标签: javascript angularjs

以下代码向MyApp的API发出http请求,以获取更新导航栏的用户个人资料数据(如姓名,照片)。

var app = angular.module('MyApp', ['ng']);

app.controller('navBarController', function($scope, $userProfile) {
    $scope.userProfile = $userProfile;
    console.log("$userProfile: " + JSON.stringify($userProfile));

    setTimeout(function() {
        console.log("$userProfile: " + JSON.stringify($userProfile));
    }, 3000);

});

app.factory('$userProfile', function($http) {
    var profile = null;
    $http.
        get('/api/v1/me').
        success(function(data) {
            profile = data;
            console.log("profile after get: " + JSON.stringify(profile));
        }).
        error(function(data, $status) {
            if ($status === status.UNAUTHORISED) {
                profile = null;
                console.log("profile if error: " + JSON.stringify(profile));
            }
        });

    console.log("profile (finally): " +  JSON.stringify(profile));
    return profile;
});

app.directive('navBar', function() {
    return {
        controller: 'navBarController',
        templateUrl: 'templates/nav_bar.html'
    }
});

我是控制台日志记录,用于检查我得到的意外结果,日志如下:

  

个人资料(最后):null

     

$ userProfile:null

     获取后的

个人资料:   {“photo”:“http://localhost:3000/img/1023.jpg”,“name”:“Utkarsh Gupta”}

     

$ userProfile:null

前两个日志消息是显而易见的,因为$http.get()是异步的,因此配置文件在函数开头定义为null。但是在$http.get()函数成功返回后,配置文件var已更新,如第三个日志消息所示,但$userProfile服务仍为空。

4 个答案:

答案 0 :(得分:1)

看起来您的服务没有注入控制器。

你有没有尝试过?

app.controller('navBarController', ["$scope", "$userProfile", function($scope, $userProfile) {}]

此处示例: https://docs.angularjs.org/guide/services

答案 1 :(得分:1)

在您的服务中,您已声明var profile = null;并触发$http api调用,然后在返回时立即返回profile变量null一旦api得到响应就会更新变量,并且你期望它应该传播到控制器,而不是这种情况。

  

由于服务本质上是singleton,因此将创建一次实例   从未创建/更新。

因此,建议不要使用您的代码来使用服务。我已经更新了下面的代码,其中service将返回一个名为load的方法,以调用从控制器触发的api,其中$scope可以直接分配响应数据。

var app = angular.module('MyApp', ['ng']);

app.controller('navBarController', function($scope, $userProfile) {
    $userProfile.load().
        success(function(data) {
            $scope.userProfile = data;
            console.log("profile after get: " + JSON.stringify($scope.userProfile));
        }).
        error(function(data, $status) {
            if ($status === status.UNAUTHORISED) {
                $scope.userProfile = null;
                console.log("profile if error: " + JSON.stringify($scope.userProfile));
            }
        });

});

app.factory('$userProfile', function($http) {
    var getProfile = function() {
      return $http.
        get('/api/v1/me');
     };

    //console.log("profile (finally): " +  JSON.stringify(profile));
    return {
       load: getProfile 
    };
});

app.directive('navBar', function() {
    return {
        controller: 'navBarController',
        templateUrl: 'templates/nav_bar.html'
    }
});
  

注意:另外,请不要将$前缀用于服务,变量,控制器名称,因为这是为AngularJS保留的,可能会创建   当您使用与AngularJS预留关键字/服务相同的名称时会发生冲突。

答案 2 :(得分:1)

您需要先修复服务(工厂)。它需要返回并反对。现在,您只是在服务中运行异步代码,控制器无法使用它。其次,一旦修复了服务(请查看下面的代码),您需要创建一个函数来获取用户配置文件。由于您正在使用异步代码,因此用户配置文件函数需要返回一个承诺。再看下面的代码,我希望它有所帮助。

var app = angular.module('MyApp', ['ng']);

app.controller('navBarController', function($scope, $userProfile) {

    $userProfile.get().then(function(response){
        $scope.userProfile = response;
    });

    setTimeout(function() {
        console.log("$userProfile: " + JSON.stringify($userProfile));
    }, 3000);

});

app.factory('$userProfile', function($http) {

    var self = {};

    self.get = getProfile;

    return self;

    function getProfile(){

        var profile = null;

        return $http.get('/api/v1/me')
            .success(function(data) {

                return data.data;

            })
            .error(function(data, $status) {

                if ($status === status.UNAUTHORISED)
                    return profile;

            });

     }
});

答案 3 :(得分:0)

不要在顶部将个人资料初始化为null,而必须将其初始化为:

var profile = {};

然后点击那个空的个人资料对象你的API返回数据,如:

$http.
        get('/api/v1/me').
        success(function(data) {
        //like this
            profile.data = data;
        })

在您的代码中,当$ userProfile-service函数完成时,它将返回简档为null。即使在$ http.get请求完成后,您的$ userProfile也具有相同的null,因为现在更新的配置文件变量不再可访问,因为它超出了范围。但是,如果您初始化并将 profile 作为对象返回,则即使在函数返回后也可以访问它,因为对象在javascript中通过引用传递。然后,您可以按照自己的方式访问控制器中的配置文件对象的内容,因为现在$ userProfile与您在上面声明的完全相同的配置文件对象而不再是null,并且在整个代码中的任何位置对该配置文件对象进行任何更新将被反映在访问该对象的任何地方。