在Angular中从工厂返回响应到控制器

Returning response from factory to controller in Angular

本文关键字:响应 控制器 返回 工厂 Angular      更新时间:2023-09-26

我有一个工厂通过api调用请求用户数据:

angular.module('MyApp')
    .factory('UserApi', function($auth,Account){
        return {
            getProfile: function()
                {
                 Account.getProfile()
                    .then(function(response){
                        return response.data; ----> returning json data ok!!
                    });
                }
        }   
});

但是当我在控制器中调用函数时,它返回给我undefined

myApp.controller('AppCtrl', function($rootScope,$state,$window,$document,$scope,$filter,$resource,cfpLoadingBar,$translate,UserApi){
$scope.user = function(){
        UserApi.getProfile().then(function(data){
            $scope.currentUser = data;
        })
    }
console.log($scope.user()); ----> undefined
});

账户工厂:

angular.module('MyApp')
    .factory('Account', function($http){
        return {
            getProfile: function(){
                 return $http.get('/api/me');
            }
        }
    });

登录控制台的错误是TypeError: Cannot read property 'then' of undefined


编辑

唯一可行的解决方案是将response.data设置为$rootScope.user,这样数据将跨控制器可用。

angular.module('MyApp')
    .factory('UserApi', function($auth,Account,$rootScope){
        return {
            getProfile: function()
                {
                 Account.getProfile()
                    .then(function(response){
                        $rootScope.user = response.data; ----> returning json data ok!!
                    });
                    return $rootScope.user;
                }
        }   
});

首先,getProfile方法应该返回一个承诺(不像在你的代码中那样未定义):

angular.module('MyApp')
    .factory('UserApi', function($auth,Account){
        return {
            getProfile: function()
                {
                 return Account.getProfile()
                    .then(function(response) {
                        return response.data;
                    });
                }
        }   
});

那么在控制器中你应该使用then callback:

myApp.controller('AppCtrl', function ($rootScope, $state, $window, $document, $scope, $filter, $resource, cfpLoadingBar, $translate, UserApi) {
    $scope.user = function () {
        UserApi.getProfile().then(function (data) {
            $scope.currentUser = data;
            console.log($scope.currentUser);
        })
    };
});

还要确保您理解同步和异步代码之间的区别,以及为什么console.log($scope.user())在这种情况下没有意义:当您尝试记录它时,如果还没有响应。相反,您提供一个回调,以便在数据到达时调用。

您试图在请求成功完成后返回数据。但是,由于这是一个ajax调用,我们不知道它何时会完成(基本上,在不同的线程上运行)。有两种方法可以解决这个问题。

1 -就像这样回电话。

angular.module('MyApp')
    .factory('UserApi', function($auth,Account){
        return {
            getProfile: function(){
                     return Account.getProfile(); // return call and resolve in controller.                   
                }
        }   
});
你可以使用promise ($q)
angular.module('MyApp')
    .factory('UserApi', function($auth,Account, $q){
        return {
            getProfile: function(){
                     var deferred = $q.defer();
                     Account.getProfile()
                       .success(function(data){
                           deferred.resolve(data);
                     });                   
                     return deferred.promise; // just return the promise
                }
        }   
});

,在你的控制器中只需要有以下内容:

myApp.controller('AppCtrl', function($rootScope,$state,$window,$document,$scope,$filter,$resource,cfpLoadingBar,$translate,UserApi){
    $scope.user = function(){
        UserApi.getProfile().then(function(data){
            $scope.currentUser = data;
            console.log($scope.currentUser);
        });
    }
});

EDITED:

得到undefined。因为:

  • $scope.user中没有return
  • 你的console.log($scope.user($scope.user())只在初始时间工作。
  • UserApi.getProfile()获取数据有时间延迟
  • 还有,你的代码有一些错误:

我可以建议:

  • 不要使用console.log($scope.user())初始时间
  • 或者,您应该获得工厂创建时的所有数据初始时间。然后,在控制器中使用UserApi.data。(但是,有时间延迟。如果请求在加载控制器之前返回响应,则可以获得成功数据。

.

angular.module('MyApp')
    .factory('UserApi', function ($auth, Account) {
        var data;
        Account.getProfile().then(function (response) {
            data = response.data;
        });
        return {
            data: data
        }
    });
myApp.controller('AppCtrl', function ($rootScope, $state, $window, $document, $scope, $filter, $resource, cfpLoadingBar, $translate, UserApi) {
    console.log(UserApi.data);
});