【问题标题】:Return a value from AngularJS API service to controller从 AngularJS API 服务返回一个值到控制器
【发布时间】:2015-04-25 22:38:58
【问题描述】:

如果我有这样的服务:

app.factory('User', function($http, User) {
    var User = function(data) {
        angular.extend(this, data);
    };
    User.prototype.create = function() {
        var user = this;

        return $http.post(api, user.getProperties()).success(function(response) {
            user.uid = response.data.uid;
        }).error(function(response) {

        });
    };

    User.get = function(id) {
        return $http.get(url).success(function(response) {
            return new User(response.data);
        });
    };

    return User;
});

如何在控制器中获取在get() 函数中创建的User

目前我拥有的是:

app.controller('UserCtrl', function($scope, User) {
    $scope.user = null;

    User.get($routeParams.rid).success(function(u) {
        $scope.user = new User(u.data);
    });
});

问题是 UserCtrl 正在获取 api 响应,而不是工厂中 success() 返回的值。我更愿意在工厂中创建新用户,而不是将 api 响应传递给控制器​​。

【问题讨论】:

    标签: javascript angularjs api service factory


    【解决方案1】:

    编辑:2015 年 5 月 5 日

    我在尝试回答这个question 时了解到deferred anti-pattern

    所以我们可以避免使用$q.defer(),而使用下面的代码来达到同样的效果。

    服务

    User.get = function(id) {
        return $http.get(url).then(function(response) {
            return new User(response.data);
        });
    };
    

    控制器

    User.get($routeParams.rid).then(function(u) {
        $scope.user = u;
    });
    

    原答案如下:

    我认为您正在寻找的是$q 服务,它允许您对来自异步$http 服务的响应进行一些后期处理,然后将其作为承诺返回给控制器。在这里查看文档https://docs.angularjs.org/api/ng/service/$q

    所以在你的工厂中注入$q 服务并改变你的User.get 函数,如下所示。

    User.get = function(id) {
        var deferred = $q.defer();
    
        $http.get(url).success(function(response) {
            deferred.resolve(new User(response.data));
        }).error(function(error) {
            deferred.reject(error);
        });
    
        return deferred.promise;
    };
    

    然后在你的控制器中你可以做

    User.get($routeParams.rid).then(function(u) {
        $scope.user = u;
    }, function(error) {
        //log error
    });
    

    【讨论】:

    • 我同意这是一种更清洁的方法。
    【解决方案2】:

    我认为你的回报有点混乱。就我个人而言,我会写成这样的

    app.factory('User', function ($http) {
    
        var user = {
            new: function (data) {
                return $http.post(api, data);
            },
            get: function (id) {
                $http.get(url).success(function (response) {
                    return user.new(response.data);
                });
            }
        };
    
        return user;
    
    });
    

    然后从你的控制器内部..

    app.controller('UserCtrl', function($scope, User) {
        $scope.user = null;
    
        User.get($routeParams.rid).success(function(u) {
            $scope.user = u.data;
        });
    });
    

    【讨论】:

    • 这就是我上面所做的。它不起作用。发生的情况是从承诺返回的数据是传递给UserCtrl
    • 我刚刚意识到你做了什么,通过使用new User,你正在创建该工厂的一个实例并返回它。除非您有另一个名为 User 的工厂。如果你这样做了,你能多写一些代码吗?
    • 我意识到我在上面写错了。 app.factory('User') 返回User。我可以放更多的代码,但它和上面的一样。只是更多的功能。有些是.prototype,有些不是get
    • 我认为这是一个错字:) 我的意思是你有创建用户的功能吗?也许像User.prototype.create...?
    • 添加了User.prototype.create的例子。
    【解决方案3】:

    有类似的问题,当我将“response.data”传递给 def.resolve 时,它​​从控制器抛出未定义。所以直接传递了响应,它起作用了。

    var def = $q.defer();
    $http.get('http://localhost:3000/api/services')
          .success(function (response) {
              ***def.resolve(response);***              
          })
          .error(function (error) {              
              def.reject(error);
          });
          return def.promise;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-15
      • 1970-01-01
      • 2013-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-23
      相关资源
      最近更新 更多