【问题标题】:Angular not updating Service variable角度不更新服务变量
【发布时间】:2016-12-04 05:29:57
【问题描述】:

以下是向 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'
    }
});

我正在控制台日志记录以检查我得到的意外结果,日志如下:

个人资料(最终):空

$userProfile: 空

获取后的个人资料: {"photo":"http://localhost:3000/img/1023.jpg","name":"Utkarsh Gupta"}

$userProfile: 空

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

【问题讨论】:

  • $ 保留用于特定角度的变量...对于用户创建的变量使用 $ 不是一个好习惯

标签: javascript angularjs


【解决方案1】:

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

你试过这样吗?

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

这里的例子: https://docs.angularjs.org/guide/services

【讨论】:

【解决方案2】:

在您的服务中,您已声明 var profile = null; 并触发 $http api 调用,然后在返回时立即返回变量 profile,即 null,稍后您将在 api 获取后更新变量响应,您期望它应该传播到控制器,但事实并非如此。

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

因此,不推荐使用您的代码来使用服务。我更新了下面的代码,其中服务将返回一个名为 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 保留关键字/服务相同的名称时会发生冲突。

【讨论】:

    【解决方案3】:

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

    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;
    
                });
    
         }
    });
    

    【讨论】:

      【解决方案4】:

      不要在顶部将 profile 初始化为 null,您必须将其初始化为:

      var profile = {};
      

      然后添加到那个空的 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 与您在上面声明的完全相同的配置文件对象不再为空,并且在整个代码中的任何位置对该配置文件对象进行任何更新将反映在访问该对象的任何位置。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多