Using factory to open a simple API

I am trying to write a factory that provides a simple user API. I'm new to AngularJS, and I'm a little confused about the factories and how to use them. I have seen other topics, but none of them are suitable for my use.

For simplicity, the only functionality I would like to get is to get all the users in the array and then pass them to the controller through the factory entered.

I saved the users in a json file (now I only want to read this file without changing the data)

users.json:

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

factory I'm trying to write should be something like this:

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

And finally, the controller call will be like this:

UsersController

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

I searched on the Internet, and it seems like it is not a good practice to use factories in this way, and if I would like to get some more features like adding / removing a new user to / from a data source, or in some way save the array in factory, this will not be the way to do this. I saw some places where using factory is like new UsersFactory() .

What would be the correct way to use factories when trying to use the API?

Is it possible to initialize a factory with an object containing the result of $http.get() , and then use it from the controller in this way?

 var usersFactory = new UsersFactory(); // at this point the factory should already contain the data consumed by the API usersFactory.someMoreFunctionality(); 
+6
source share
5 answers

I see nothing wrong with your factory. If I understand correctly, you want to add functionality. A few small changes will make this possible. Here is what I would do (note that calling getAllUsers removes any changes):

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

Normally, add and remove calls would be http requests (but this is not what you are asking in the question). If the request succeeds, you know that your user interface can add / remove a user from the view.

+2
source

I like the fact that my API factories return objects instead of one endpoint:

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

Thus, if you have other endpoints associated with the user, you can use them in one factory. Also, my preference is to just return the $http promise directory and use then() in the controller or wherever you enter factory.

+1
source

I am really a fan of permit route promises . Here is an example of John Papa. I will explain later how to apply this to what you are doing:

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

Basically, before your route loads, you get the requested request data (in your case, your "user" is JSON.) You have several options here ... You can store all this data in the Users factory (by the way, your factory looks great) and then in your controller just call Users.getAll , which can just return an array of users. Or , you can simply pass Users from the promise of a route solution, as John Papa does in his example. I canโ€™t do it as fairly as the article he wrote, so I would seriously recommend reading it. This is a very elegant approach, IMHO.

+1
source

I usually use a factory something like this:

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

What could you name:

 usersFactory.query(); 

Since this is a promise, you can also use the .then method with it.

0
source

$ http is a promise that means you need to check if your call is working or not.

try to implement this type of architecture in the controller

 $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 }); 
0
source

Source: https://habr.com/ru/post/988792/


All Articles