2015-06-09 4 views
6

Я пытаюсь написать фабрику, которая предоставляет простой API пользователей. Я новичок в AngularJS, и я немного запутался в отношении фабрик и как их использовать. Я видел другие темы, но ни один из них не подходит для моего использования.Использование фабрики для предоставления простого API

Для простоты единственной функциональностью, которую я хотел бы достичь, является получение всех пользователей в массиве, а затем передача их контроллеру через внедренную фабрику.

Я хранила пользователей в файле JSON (теперь я только хочу, чтобы прочитать этот файл, не изменяя данные)

users.json:

[ 
{ 
    "id": 1, 
    "name": "user1", 
    "email": "[email protected]" 
}, 
{ 
    "id": 2, 
    "name": "user2", 
    "email": "[email protected]" 
} 
] 

Завод Я пытаясь написать должно быть что-то вроде этого:

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(); 
+0

Я всегда употреблял api с помощью '$ resource', который делает много работы для вас, когда вы занимаетесь спокойной apis. но в вашем случае простой http должен быть прекрасным, так как вы просто работаете с простым файлом json. вы не потребляете api. –

+0

Вы собираетесь делать несколько вызовов 'getAllUsers()' или это всего лишь один вызов для жизни вашего приложения? – allienx

+0

@KevinB Я использую простой json просто для простоты, реальное использование этого приложения будет с RESTful API, но с точки зрения клиента это не имеет большого значения. –

ответ

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

Обычно add и remove вызов будут http запросов (но это не то, что вы просите в этом вопросе). Если запрос преуспевает, вы знаете, что ваш пользовательский интерфейс может добавлять/удалять пользователя из представления.

+0

Спасибо за ответ, есть способ инициализировать возвращенный объект данными, потребляемыми '$ http.get()', и просто используйте функции 'add()' и 'remove()'? –

+0

Теперь вы попадаете в 'resolve'. Используете ли вы ngRoute или AngularUI Router? –

+0

Я использую AngularUI Router. –

0

Я обычно использую фабричного что-то вроде этого:

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

    }]) 

Что вы могли бы назвать с:

usersFactory.query(); 

Как это обещание вы все еще можете использовать .then метод с это тоже

+0

Я бы тоже рекомендовал использовать этот урок: [угловой] (https://docs.angularjs.org/tutorial/step_00) –

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 
    }); 
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() { 
    ... 
    } 
}]); 

Таким образом, если у вас есть какие-либо другие конечные точки пользователей, с которыми вы можете потреблять их все на одном заводе. Кроме того, мое предпочтение заключается в том, чтобы просто вернуть каталог обещаний и использовать в контроллере then() или где бы вы ни вводили завод.

1

Я действительно являюсь поклонником route resolve promises. Вот пример Джона Папы. Я объясню потом, как применить это к тому, что вы делаете: (. В вашем случае, ваш «пользователи» JSON)

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

В принципе, перед вашим маршрутом нагрузок, вы получите данные запроса вам нужны Вы несколько вариантов отсюда ... Вы можете хранить все эти данные на фабрике Users (кстати, ваш завод отлично выглядит), а затем в вашем контроллере просто позвоните Users.getAll, который может просто вернуть массив пользователей. Или, вы можете просто передать в usersс маршрута разрешить обещание, как и Джон Папа в своем примере. Я не могу сделать так же справедливо, как и статью, которую он написал, поэтому я бы серьезно рекомендовал ее прочитать. Это очень элегантный подход, ИМХО.

+0

вы можете получить некоторое время ожидания между пользователем, изменяющим состояние (нажатием ссылки или кнопкой, вызывающей изменение состояния) и фактическим отправлением в новое состояние. imo лучший пользовательский интерфейс заключается в том, чтобы сразу перейти к новому состоянию и получить контролер за выборку данных, а затем отобразить ее, когда она будет готова. – JesseDahl

Смежные вопросы