使用$ http和$ q获取数据

时间:2014-01-07 21:38:33

标签: angularjs http q

我正在尝试使用$ q和$ http从服务器获取数据并等待直到检索到数据。在检索数据后,我想操纵它。

这是我的服务方法,它从服务器获取数据:

application
.factory('service', function ($http,$q) {
  return { 
     fetch: function(url) {
         var deferred = $q.defer();
         $http.get(url).success(function(data){             
             deferred.resolve(data);
         }).error(function(){               
           deferred.reject("An error occured while fetching items");
         });    
         return deferred.promise;
      }        
  };
}); 

使用数据的控制器如下所示:

service.fetch(url).then(function(data){
  $scope.data = data;
  },
function(errorMessage){
  $scope.error=errorMessage;
});
$scope.data = ...manipulate data

问题在于角度在获取之前操纵数据。任何建议如何解决这个问题将非常感激。

3 个答案:

答案 0 :(得分:4)

如果您需要处理服务呼叫中的数据,一个不错的选择是使用$http服务中的transformResponse option。它基本上允许您在解决承诺之前完全弄乱响应。

观看此视频了解演示内容。 https://egghead.io/lessons/angularjs-transformresponse

这是一个示例转换函数。

app.factory('searchResponseTransformer', function () {
    return function (data) {
        data = JSON.parse(data);
        if (data.length) {
            // Do data manipulation here
        }
        return data;
    };
});

然后您可以在服务中使用此转换功能。

app.factory('searchService', function ($http, searchResponseTransformer) {
  return { 
    search: function(searchTerm) {
      return $http({
        method: "GET",
        url: "/search",
        params: { q: searchTerm },
        transformResponse: searchResponseTransformer
      });
    }
  }        
}); 

然后您可以从控制器使用此服务。

app.controller('searchCtrl', function ($scope, searchService) {
  $scope.searchTerm = "";
  $scope.searchResults = [];

  $scope.search = function() {
    searchService
      .search($scope.searchTerm)
      .success(function(data) {
        $scope.searchResults = data;
      });
  }
}); 

你的观点看起来像这样......

<div ng-controller="searchCtrl">
  <p><input type="text" ng-model="searchTerm" ></p>
  <ul>
    <li ng-repeat="item in searchResults">{{item.description}}</li>
  </ul>
</div>

答案 1 :(得分:2)

问题是$scope.data = ...service.fetch(url)被称为而不是之后运行。调用成功回调时,AJAX调用service.fetch(url)返回数据,因此正确的代码是:

service.fetch(url).then(
    function(data) {
        $scope.data = data; // keeping it for anyone else that needs it, e.g. the view
        $scope.data = ... // manipulate data HERE
    },
    function(errorMessage) {
        ...
    }
);

答案 2 :(得分:1)

在获取数据之前,不应该操纵数据。 Promise会立即返回,因此您的操作将被当时的回调覆盖。你应该做的是操纵当时回调中的数据:

service.fetch(url).then(function(data){
    $scope.data = ...manipulate data
  },
  function(errorMessage){
    $scope.error=errorMessage;
});

但是,要改进此代码,因为它不是非常易读,您可以创建一个服务方法来为您执行此操作。作为$ http的替代,我建议你使用Restangular。它略微面向对象。查看我写的这篇博文:

http://ath3nd.wordpress.com/2013/08/05/15/

Restangular,就像$ http一样,有承诺的概念,所以你可以这样做:

function fetch(url){
   var deferred = $q.defer();
   Restagular.one(url).get({})
   .then(function(result){
       //do your manipulation, e.g.
       result.newlyCreatedProp = 'newlyCreatedProp';
       deferred.resolve(result);
   });
   return deferred.promise;
}

然后你可以在你的控制器中做到这一点:

service.fetch().then(function(data){
   $scope.data = data;
});

由于承诺会立即返回,因此会立即生效。