【问题标题】:Why is this factory returning a $$state object instead of response.data?为什么这个工厂返回一个 $$state 对象而不是 response.data?
【发布时间】:2016-02-23 22:54:59
【问题描述】:

所以我在服务器中有一组对象,我想在页面加载时填充 ng-repeat。

我做了一个工厂,它从服务器上的资源中获取列表,如下所示:

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

之前在状态声明中使用 ui-router 和 resolve 属性时,我已经让这段代码工作过。但是,当将此工厂直接注入我的控制器时,我得到的不是 response.data,而是 $$state 对象。

我的控制器如下所示:

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

【问题讨论】:

标签: angularjs state factory


【解决方案1】:

$http 服务返回的内容(因此objectArray 服务是)称为承诺。您可以通过注册一个回调函数来访问实际数据,该回调函数将在数据可用时调用,即当对 http 请求的响应从服务器返回时:

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

使用resolve时你可以直接访问数据的原因是,当resolve函数返回一个promise时,路由器会等待promise被解析。只有这样,它才会从 Promise 中提取数据并将数据注入到控制器中。

为了更好地理解 Promise,您可以阅读 the following article(及其 sequel)。

【讨论】:

    【解决方案2】:

    正如@JB Nizet 所注意到的,你的代码很好,只需在控制器中解决它 这是工作演示

    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>

    【讨论】:

    • 返回数据的承诺(通过承诺链)而不是 HTTP 响应的承诺实际上是一件好事。 OP的工厂非常好。
    • 你的第二个例子是一个坏主意:现在调用者无法知道http请求是否/何时失败。您还应该阅读blog.ninja-squad.com/2015/05/28/angularjs-promises
    • @JBNizet 我确实知道在 2 个例子中,必须有 2 个回调,也更新了答案,你确实是对的
    • 不,不应该有任何回调。兑现承诺是正确的方式。这就是他们的目的。
    • @JBNizet 我不同意,可能有条件你不需要从承诺返回任何东西,只需执行你的回调,但仍然取决于用例,在那个特定的例子中,我是说成功响应和错误响应的 2 个回调。而且我认为提供以不同方式做事的选择可以帮助人们更多
    【解决方案3】:

    错误

    @ 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 是问题所在。

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

    解决方案: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,
            });
    });
    

    竖起大拇指!.. =)

    【讨论】:

      猜你喜欢
      • 2020-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-23
      • 2017-09-19
      • 1970-01-01
      相关资源
      最近更新 更多