使用工厂公开一个简单的API

时间:2015-06-09 15:16:05

标签: javascript angularjs factory

我正在尝试编写一个公开简单用户API的工厂。我是AngularJS的新手,我对工厂以及如何使用它们有点困惑。我见过其他主题,但没有一个与我的用例很匹配。

为了简单起见,我想要实现的唯一功能是将所有用户放入阵列中,然后通过注入的工厂将它们传递给控制器​​。

我将用户存储在json文件中(现在我只想读取该文件,而不修改数据)

users.json:

[
{
    "id": 1,
    "name": "user1",
    "email": "a@b.c"
},
{
    "id": 2,
    "name": "user2",
    "email": "b@b.c"
}
]

我想写的工厂应该是这样的:

UsersFactory:

app.factory('usersFactory', ['$http', function ($http) {
    return {
        getAllUsers: function() {
            return $http.get('users.json').then(
                function(result) {
                    return result.data;
                },
                function(error) {
                    console.log(error);
                }
            );
        }
    };
}]);

最后,控制器调用将是这样的:

UsersController

app.controller('UsersCtrl', ['$scope', 'usersFactory', function($scope, usersFactory){
    usersFactory.getAllUsers().then(function (result) {
        $scope.users = result;
    });
}]);

我在网上搜索过,似乎以这种方式使用工厂并不是一个好习惯,如果我想实现更多功能,例如在数据源中添加/删除新用户,或以某种方式将数组存储在工厂内,这不是这样做的方法。我见过一些使用工厂的地方就像new UsersFactory()

尝试使用API​​时使用工厂的正确方法是什么?

是否可以使用包含$http.get()结果的对象初始化工厂,然后以这种方式从控制器中使用它?

var usersFactory = new UsersFactory(); // at this point the factory should already contain the data consumed by the API
usersFactory.someMoreFunctionality();   

5 个答案:

答案 0 :(得分:2)

我发现你的工厂没有任何问题。如果我理解正确,您想要添加功能。一些小的改变会使这成为可能。这就是我要做的事情(请注意,调用getAllUsers会消除所有更改):

app.factory('usersFactory', ['$http', function ($http) {
  var users = [];
  return {
      getAllUsers: function() {
          return $http.get('users.json').then(
              function(result) {
                  users = result.data;
                  return users;
              },
              function(error) {
                  users = [];
                  console.log(error);
              }
          );
      },
      add: function(user) {
          users.push(user);
      },
      remove: function(user) {
          for(var i = 0; i < users.length; i++) {
              if(users[i].id === user.id) { // use whatever you want to determine equality
                  users.splice(i, 1);
                  return;
              }
          }
      }
  };
}]);

通常,addremove来电是http次请求(但这不是您在问题中要求的)。如果请求成功,您就知道您的UI可以在视图中添加/删除用户。

答案 1 :(得分:1)

我喜欢我的API工厂返回对象而不是只返回一个端点:

app.factory('usersFactory', ['$http', function ($http) {
  return {
    getAllUsers: getAllUsers,
    getUser: getUser,
    updateUser: updateUser
  };

  function getAllUsers() {
    return $http.get('users.json');
  }

  function getUser() {
    ...
  }

  function updateUser() {
    ...
  }
}]);

这样,如果您有任何其他与用户相关的端点,您可以在一个工厂中使用它们。此外,我的偏好是只返回$http promise目录并使用控制器中的then()或您注射工厂的地方。

答案 2 :(得分:1)

我真的是route resolve promises的粉丝。这是John Papa的例子。我将在后面解释如何将其应用于您正在做的事情:

// route-config.js
angular
    .module('app')
    .config(config);

function config($routeProvider) {
    $routeProvider
        .when('/avengers', {
            templateUrl: 'avengers.html',
            controller: 'Avengers',
            controllerAs: 'vm',
            resolve: {
                moviesPrepService: moviesPrepService
            }
        });
}

function moviesPrepService(movieService) {
    return movieService.getMovies();
}

// avengers.js
angular
    .module('app')
    .controller('Avengers', Avengers);

Avengers.$inject = ['moviesPrepService'];
function Avengers(moviesPrepService) {
      var vm = this;
      vm.movies = moviesPrepService.movies;
}

基本上,在您加载路线之前,您将获得所需的请求数据(在您的情况下,您的&#34;用户&#34; JSON。)您可以从此处获得多个选项...您可以存储所有数据一个Users工厂(顺便说一下,你的工厂看起来很好),然后在你的控制器中,只需调用Users.getAll,它就可以返回用户数组。 ,您可以从路径解析承诺传递users ,就像John Papa在他的示例中所做的那样。我不能像他写的文章那样做正义,所以我会认真地推荐阅读它。这是一种非常优雅的方法,恕我直言。

答案 3 :(得分:0)

我通常使用这样的工厂:

.factory('usersFactory', ['$resource',
  function($resource){
    return $resource('http://someresource.com/users.json', {}, {
        query: {
            method:'GET',
            isArray:true
            }
        })

  }])

您可以致电:

usersFactory.query();

由于这是一个承诺,你仍然可以使用.then方法

答案 4 :(得分:0)

$ http是一种承诺,意味着您必须检查您的来电是否有效。

所以尝试在控制器中实现这种类型的架构

$http.get('users.json')
  .success(function(response) {
    // if the call succeed
       $scope.users = result;
  })
  .error(function(){console.log("error");})
  .then(function(){
   //anything you want to do after the call
   });