質問

I have a factory called "Server" which contains my methods for interaction with the server (get/put/post/delete..). I managed to login and get all data successfully when I had all my code in my controller. Now that I want to separate this code and restructure it a little bit I ran into problems. I can still login and I also get data - but data is just printed; I'm not sure how to access the data in controller? I saw some ".then" instead of ".success" used here and there across the web, but I don't know how exactly.

This is my factory: (included in services.js)

app.factory('Server', ['$http', function($http) {
    return {
        // this works as it should, login works correctly
       login: function(email,pass) {
            return $http.get('mywebapiurl/server.php?email='+email+'&password='+pass').success(function(data) {
                console.log("\nLOGIN RESPONSE: "+JSON.stringify(data));
                if(data.Status !== "OK")
                   // login fail
                   console.log("Login FAIL...");
                else
                   // success   
                   console.log("Login OK...");
                });
        },

        // intentional blank data parameter below (server configured this way for testing purposes)
        getAllData: function() {
            return $http.get('mywebapiurl/server.php?data=').success(function(data) {
                console.log("\nDATA FROM SERVER: \n"+data); // here correct data in JSON string format are printed
            });
        },
    };

}]);

This is my controller:

app.controller("MainController", ['$scope', 'Server', function($scope, Server){ 

   Server.login();   // this logins correctly   

   $scope.data = Server.getAllData(); // here I want to get data returned by the server, now I get http object with all the methods etc etc.

  …. continues … 

How do I get data that was retrieved with $http within a factory to be accessible in controller? I only have one controller.

Thanks for any help, I'm sure there must be an easy way of doing this. Or am I perhaps taking a wrong way working this out?

EDIT: I also need to be able to call factory functions from views with ng-click for instance. Now I can do this like this:

// this is a method in controller
$scope.updateContacts = function(){
    $http.get('mywebapiURL/server.php?mycontacts=').success(function(data) {
        $scope.contacts = data;
    }); 
};

and make a call in a view with ng-click="updateContacts()". See how $scope.contacts gets new data in the above function. How am I supposed to do this with .then method?(assigning returned data to variable)

My question asked straight-forwardly:

Lets say I need parts of controller code separated from it (so it doesn't get all messy), like some functions that are available throughout all $scope. What is the best way to accomplish this in AngularJS? Maybe it's not services as I thought …

役に立ちましたか?

解決

The trick is to use a promise in your service to proxy the results.

The $http service returns a promise that you can resolve using then with a list or success and error to handle those conditions respectively.

This block of code shows handling the result of the call:

var deferred = $q.defer();
$http.get(productsEndpoint).success(function(result) {
    deferred.resolve(result);
}).error(function(result) { deferred.reject(result); });
return deferred.promise;

The code uses the Angular $q service to create a promise. When the $http call is resolved then the promise is used to return information to your controller. The controller handles it like this:

app.controller("myController", ["$scope", "myService", function($scope, myService) {
    $scope.data = { status: "Not Loaded." };
    myService.getData().then(function(data) { $scope.data = data; });
}]);

(Another function can be passed to then if you want to explicitly handle the rejection).

That closes the loop: a service that uses a promise to return the data, and a controller that calls the service and chains the promise for the result. I have a full fiddle online here: http://jsfiddle.net/HhFwL/

You can change the end point, right now it just points to a generic OData end point to fetch some products data.

More on $http: http://docs.angularjs.org/api/ng.%24http More on $q: http://docs.angularjs.org/api/ng.%24q

他のヒント

$http.get retuns a HttpPromise Object

 Server.getAllData().then(function(results){

   $scope.data = results;
 })
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top