-->

Why is this factory returning a $$state object ins

2020-08-22 09:42发布

问题:

So I have a collection of objects in the server I want to populate an ng-repeat when the page loads.

I had a made a factory which fetched the list from a resource on the server, like so:

  app.factory('objectArray', ['$http', function($http) {
      // This is returning a $$state object
      // instead of response.data...
      return $http.post('/get_collection').then(function(response) {
          console.log(response.data);
          return response.data;
      });
  }]);

I've had this code work before when using ui-router and the resolve property in the state declaration. However when injecting this factory directly into my controller, instead of getting response.data I am getting a $$state object.

My controller looks like this:

 app.controller('applicationController', ['$scope', 'objectArray', function($scope, objectArray) {
     $scope.array = objectArray;
     console.log($scope.array);
 }]);

回答1:

What the $http service returns (and thus the objectArray service is) is called a promise. You can access the actual data by registering a callback function that will be called when the data is available, i.e. when the response to the http request comes back from the server:

objectArray.then(function(data) {
    $scope.array = data;
});

The reason you directly have access to the data when using resolve is that the router, when the resolve function returns a promise, waits for the promise to be resolved. And only then, it extracts the data from the promise and injects the data into the controller.

To better understand promises, you could read the following article (and its sequel).



回答2:

As @JB Nizet noticed, you code is fine, just resolve it in controller Here's working demo

angular.module('app', []);
angular.module('app').factory('objectArray', ['$http', function($http) {
  // This is returning a $$state object
  // instead of response.data...
  ////// changed request type and url for the sake of example
  return $http.get('http://jsonplaceholder.typicode.com/posts/1')
.then(function(response) {
  console.log(response.data);
  return response.data;
});
}]);
angular.module('app').controller('applicationController', ['$scope', 'objectArray', function($scope, objectArray) { 
  //////resolve it here
  objectArray.then(function(successResponse){
    $scope.array = successResponse;
    console.log($scope.array);
  });
}]);
angular.bootstrap(document.body, ['app']);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="applicationController">
  <h5>Hello {{array.title}}</h5>
</div>



回答3:

errors

@ angular.js:14800 [AngularJS - Leaflet] The marker definition is not valid.
17:49:07.437 angular.js:14800 [AngularJS - Leaflet]  Received invalid data on the marker $promise.
17:49:07.438 angular.js:14800 [AngularJS - Leaflet] The marker definition is not valid.
17:49:07.439 angular.js:14800 [AngularJS - Leaflet]  Received invalid data on the marker $resolved.

$$state was the problem.

markersFactory.query().$promise.then(function(data) {
    // open_street_maps to replace google maps
    angular.extend($scope, {
        center: {
            lat:   40.7231572,
            lng:  -73.988501,
            zoom: 13,
        } ,
        markers: data,
        tiles: tilesDict.opencyclemap,
    });
});

the SOLUTION: angular.copy

markersFactory.query().$promise.then(function(data) {
    $scope.markers        = data;
    // open_street_maps to replace google maps
    angular.extend($scope, {
        center: {
            lat:   40.7231572,
            lng:  -73.988501,
            zoom: 13,
        } ,
        markers: angular.copy($scope.markers),
        tiles: tilesDict.opencyclemap,
        });
});

thumbs up!.. =)