简体   繁体   中英

Angular http returns $$state object

I have the following factory defined:

angular.module("account").factory("users",["$http",
    function(a){
      return {
         getUser: function(){
            return a.get("/user/me").then(function(r){
                return r.data;
            });
        }
    };
  }
]);

And my controller:

angular.module("test.controllers",["account"])
.controller("TestCtrl",["$scope","users",
    function(a,u){
        a.user = u.getUser();
        console.log(a.user);
}]);

Here's the console.log:

 d {$$state: Object, then: function, catch: function, finally: function} $$state: Object status: 1 value: Object user: Object__v: 0 _id: "54c1fg29f36e117332000005" temp: "1ce3793175e0b2548fb9918385c2de09"  __proto__: Object __proto__: Object __proto__: Object __proto__: Object

The above code is returning a state object instead of the user object. But from the log, the state object has the user object within value. How do i get the user object? Or am i doing this completely wrong?

I know the other way is to return the $http.get and call the then() method within controller. But I'll be using the user object frequently and if i'm calling the then() method in controller, its almost same as using the $http.get in controller instead of the factory.

JavaScript I/O is usually, including in this case asynchronous. Your getUser call returns a $q promise . In order to unwrap it you have to chain to it and then unwrap it as such:

angular.module("test.controllers",["account"])
.controller("TestCtrl",["$scope","users",
    function(a,u){
        u.getUser().then(function(user){
            a.user = user;
            console.log(a.user);
        });
}]);

If you're using routing you might also want to look into the resolve option in the route. Also see this related question .

angular.module("account").factory("users",["$http",
    function(a){
      var factObj = {
         user: null,
         getUser: function(){
            return a.get("/user/me").then(function(r){
                factObj.user = r.data;
            });
        }
      factObj.getUser();

      return factObj;
    };
  }
]);

angular.module("test.controllers",["account"])
.controller("TestCtrl",["$scope","users",
    function(a,u){
        a.userService = u;
}]);

In your view

<div ng-controller="TestCtrl as test">{{test.userService.user}}</div>

Edits based on comments, true this would not work with the controller or view as you probably had them, but this pattern works well and removes the need to have .then in every controller that may re-use the data.

Typically storing your model in the factory or service that deals with fetching the data makes for an easier path to getting the data into every view where you need it. Down side here is you'd be fetching the user when this factory is referenced instead of explicitly firing the getUser function from the controller. If you want to get around that you can store the promise from the first time it's requested in the getUser function and just return that promise for all subsequent calls if it's already set, this way you can call getUser multiple times without repeating the API request.

I have here a similar scenario.. I hope it helps somebody...

my factory ..

 angular.module('programList.services',[])
    .factory('PROGRAMS', function($http) {
     return {
       getprogramList: function() {
       return $http.get('/api/programs/list').then(function(result) {
       return result.data[0];
       });
      }
     };
    });

This is my controller ..

 angular.module('programList.services'])
 .controller('tviProgramsController',
    function($scope,$state,$stateParams,PROGRAMS){
        //this is the call to access the list as answered by Benjamin Above using then on success 
        PROGRAMS.getprogramList().then(function(list){
                  $scope.programlist = list;
              });
  });

;

This is on the router on server side...

  var express     = require('express'),
     programscontroller = require(path + 'programservercontroller'),
     router         = new express.Router();
     router.get('/api/programs/list', programscontroller.programlist);

This is the module for mysql call

var con   = require('../../database/dbcon'),
mysql = require('mysql');

module.exports.programlist = function(req, res){
 var data = req.params.data;
 var sql = "CALL `sp_programlist`";
  con.query(sql, function(err, result) {
      if(err){
          throw err;
      } else {
          res.send(JSON.stringify(result));
      }
     });
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM