0

I have a newbie question here.

I am coding a factory in angularJS. With it I want to have a list of users, and also a method to fill it.

So this is my code ...

The factory

app.factory("usuariosFactory", function ($http) {


    var f = {};

    f.users = [];

    f.getUsers = function (callback) {
        var token = window.localStorage.getItem("_token");


        $http.get("http://localhost:8000/api/user/list?token=" + token).then(function (response) {
            f.users = response.data.users;

            /* the console.log outputs OK with the users from the server */
            console.log(f.users);
        });
    }; 

    return f;
});

The controller

app.controller("usuariosController", function ($scope, usuariosFactory) {
    var scope = this;

    /* link users from factory to controllerś scope .. NOT WORKING */
    usuariosFactory.getUsers();

    scope.usuarios = usuariosFactory.users;
});

I am hitting my head to the desk right now. I dont understand how to achieve this.

georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • See [Why are Callbacks from Promise `.then` Methods an Anti-Pattern](https://stackoverflow.com/questions/35660881/why-are-callbacks-from-promise-then-methods-an-anti-pattern). – georgeawg May 26 '18 at 05:48
  • See also [You're Missing the Point of Promises](https://blog.domenic.me/youre-missing-the-point-of-promises/). – georgeawg May 26 '18 at 05:49

2 Answers2

0

You should just return the promise from the factory to controller

Then in controller, you should subscribe to that promise and assign data to your scope variable

Factory:

app.factory("usuariosFactory", function ($http) {
    var f = {};
    f.users = [];
    f.getUsers = function (callback) {
        var token = window.localStorage.getItem("_token");
        return $http.get("http://localhost:8000/api/user/list?token=" + token);
    };
    return f;
});

Controller:

app.controller("usuariosController", function ($scope, usuariosFactory) {
    var scope = this;
    usuariosFactory.getUsers().then(function (response) {
        scope.usuarios = response.data;
    });
});
Sravan
  • 18,467
  • 3
  • 30
  • 54
-1

The usuariosFactory.getUsers is an asynchronous function, due to $http.get inside. So, to have your data, you have to use the callback function that you've already put in the getUsers. The code should be like:

usuariosFactory.getUsers(function () {
    scope.usuarios = usuariosFactory.users;
});

and after the f.users = response.data.users; you have to call the callback function. Like this:

f.getUsers = function (callback) {
    var token = window.localStorage.getItem("_token");
    $http.get("http://localhost:8000/api/user/list?token=" + token).then(function (response) {
        f.users = response.data.users;
        callback();
    });
};

That way you will handle ansynchronous functions with a callback funtion. Another way to do this is with promises, in that way, your code should be like this:

The factory

app.factory("usuariosFactory", function ($http, $q) {
    var f = {};
    f.users = [];

    f.getUsers = function (callback) {
        var token = window.localStorage.getItem("_token");
        var deferred = $q.defer(); // Creates the object that handles the promise
        $http.get("http://localhost:8000/api/user/list?token=" + token)
            .then(function (response) {
                f.users = response.data.users;
                deferred.resolve('You can pass data!'); // Informs that the asynchronous operation have finished
            });
        return deferred.promise; // Returns a promise that something will happen later
    };

    return f;
});

The controller

app.controller("usuariosController", function ($scope, usuariosFactory) {
    var scope = this;

    // Now you can use your function just like you use $http
    // This way, you know that watever should happen in getUsers, will be avaible in the function
    usuariosFactory.getUsers()
        .then(function (data) {
            console.log(data) // Print 'You can pass data!'
            scope.usuarios = usuariosFactory.users; 
        });
});
Alyson Maia
  • 802
  • 5
  • 14
  • 2
    Classic [deferred antipattern](https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it) - I recommend avoiding this type of factory and returning the promise directly instead. – Lex May 25 '18 at 21:34
  • @Lex, you mean returning http.get() instead? –  May 25 '18 at 23:10
  • I mean returning the promise that is created as a result of calling `$http.get()`. Read the answer at the link - dealing with promises is a pretty integral part of Angular and you should understand the implications of using them. – Lex May 25 '18 at 23:13
  • See [Why are Callbacks from Promise `.then` Methods an Anti-Pattern](https://stackoverflow.com/questions/35660881/why-are-callbacks-from-promise-then-methods-an-anti-pattern). – georgeawg May 26 '18 at 05:45
  • to everyone of you, thanks very much, this post really took me through a lot of reading. Now at least I know how I should deal with promises in the proper way according to theory. –  May 28 '18 at 11:00
  • I will not mark this answer as correct just because there is another one that exactly handles the pattern accepted by the theory. but this answer works ... it is just not well embarecd to the theory behind promises –  May 28 '18 at 11:01