Angular http возвращает объект состояния $$

Я определил следующий factory:

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

И мой контроллер:

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

Здесь 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

Приведенный выше код возвращает объект состояния вместо объекта пользователя. Но из журнала объект состояния имеет объект пользователя в пределах значения. Как получить объект пользователя? Или я делаю это совершенно неправильно?

Я знаю, что другим способом является возвращение $http.get и вызов метода then() в контроллере. Но я часто использую объект пользователя, и если я вызываю метод then() в контроллере, он почти такой же, как с использованием $http.get в контроллере вместо factory.

Ответы

Ответ 1

JavaScript I/O обычно, в том числе в этом случае асинхронный. Ваш вызов getUser возвращает обещание в $q. Чтобы развернуть его, вам нужно подключиться к нему, а затем развернуть его как таковое:

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

Если вы используете маршрутизацию, вы также можете просмотреть опцию resolve на маршруте. Также см. этот связанный вопрос.

Ответ 2

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

На ваш взгляд

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

Редактирование на основе комментариев, правда, это не будет работать с контроллером или представлением, поскольку вы, вероятно, имели их, но этот шаблон работает хорошо и устраняет необходимость иметь. then в каждом контроллере, который может повторно использовать данные.

Обычно сохранение вашей модели в factory или службе, которая занимается извлечением данных, упрощает путь к получению данных во все виды, где вам это нужно. Внизу вы будете получать пользователя, когда этот factory ссылается вместо явного включения функции getUser из контроллера. Если вы хотите обойти это, вы можете сохранить обещание с первого раза, когда он запросил функцию getUser, и просто вернуть это обещание для всех последующих вызовов, если он уже установлен, таким образом вы можете вызвать getUser несколько раз, не повторяя запрос API.

Ответ 3

У меня есть похожий сценарий.. Надеюсь, это поможет кому-то...

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

Это мой контроллер.

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

;

Это на маршрутизаторе на стороне сервера...

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

Это модуль для вызова mysql

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