Angular移动成功递归回调服务

时间:2015-04-10 21:06:57

标签: angularjs recursion promise angular-services angular-http

我有一个返回$ http promises的服务。这工作正常,但我需要做一个递归调用,以防列表返回超过100个项目。再次,这可行,但我为每个控制器重复自己。我无法将递归卸载到服务并仍然获得最终结果。也许$q会有帮助吗?

// service
function List ($http) {
  var headers = {'Accept': 'application/json;odata=verbose'}
    , listService = {
        getByName: function (listName) {
          return $http({
            method: 'GET'
          , url: '/_api/web/lists/getByTitle(\'' + listName + '\')/items'
          , headers: headers
          });
        }

      , getByUrl: function (url) {
          return $http({
            method: 'GET'
          , url: url
          , headers: headers
          })
        }
  };

  return listService;
}

// controller
function Calendar ($scope, List) {
  $scope.events = [];

  List.getByName('Calendar').success(function (response) {
    $scope.events = response.d.results;
    if (response.d.__next) {
      List.getByUrl(response.d.__next).success(recursiveSuccess);
    }
  });

  function recursiveSuccess (response) {
    $scope.events = $scope.events.concat(response.d.results);
    if (response.d.__next) {
      List.getByUrl(response.d.__next).success(recursiveSuccess);
    }
  }
}

2 个答案:

答案 0 :(得分:0)

由于每次调用都会为您提供下一个端点的URL,因此必须在连续的HTTP调用中完成。就承诺而言,它将在概念上如此完成:

return firstCall.then(function(data){
  return secondCall(data);
})
// another .then
// another .then
.then(function(data){
  return lastCall(data);
});

这里的每个NCall都是一个函数,它接收上一个调用的数据并返回下一个聚合数据的承诺,lastCall返回最终的聚合数据。

如果要将其转换为递归函数,它将如下所示:

function getItemsFrom(url, items){

  return $http.get(url).then(function(response){

    items = items.concat(response.data.items);

    if (response.data.next){
      return getItemsFrom(response.data.next, items);
    } else {
      return items;
    }
  });
}

数据为:

{
  "next": "url/to/data2.json",
  "items": [1, 2, 3]
}

唯一剩下的就是初次通话:

.factory("fooSvc", function($http){
  function getItemsFrom(url, items){
    // as above
  }

  return {
    getItems: function(){
      return getItemsFrom("url/to/data1.json", []);
    }
  };
});

Demo

答案 1 :(得分:0)

是的,我遇到了类似的问题,我必须在我的服务中的方法中进行多次调用,并使用$q解决了问题。一旦你学会了如何使用它,它就会非常强大。

在您的服务方式中:

function promiseYoullCallMeWhenYoureComplete () {
    var deferred = $q.defer();
    var events = [];

    startMyQuery();

    return deferred.promise;

    ////////////

    function startMyQuery () {
       List.getByName('Calendar').then(success, error);
    }

    function success (response) {
        // perform success actions
        events = angular.extend(events, response.data.d.results);

        // run next query or exit if complete
        if (response.data.next) {
           return startMyQuery();
        }

        // no more queries, so exit and return my combined events array
        return deferred.resolve(events);
    }

    function error (response) {
        return deferred.reject(response);
    }
}

然后在您的控制器中,例如:

List.promiseYoullCallMeWhenYoureComplete().then(success, error);

///////////

function success (events) {
    $scope.events = events;
}

function error (response) {
    console.error("Error:", response);
}

通过这种方式,您的服务可以进行$ http查询,直到奶牛回家,但您的控制器只会收到一个响应来处理(要么成功,所有结果都会通过您的{{1因为你可以将所有逻辑移动到服务中,所以你的控制器非常干净。