简体   繁体   English

Angular $ q返回承诺多个$ http调用

[英]Angular $q returning promise multiple $http calls

I'm working on an $http call that loops over each of multiple api's and returns all of the data in one object. 我正在进行$ http调用,它遍历多个api中的每一个并返回一个对象中的所有数据。 I usually have the promise ready to resolve when the $http call has been made. 我通常已经准备好在$ http调用时解决。 Similar to this: 与此类似:

function getAllData(api) {
    return $http({
        method: 'GET',
        url: '/api/' + api
    })
    .then(sendResponseData)
    .catch (sendGetVolunteerError);
}

The current function I have loops over each api and pushes each object in the api into an array and then pushes it into an overall array. 当前函数我遍历每个api并将api中的每个对象推送到一个数组中,然后将其推送到整个数组中。 I had this functioning, returning an multi-dimensional array, which needed to be flattened out. 我有这个功能,返回一个多维数组,需要被展平。

I'd like to return this in a promise, but am returning undefined . 我想在一个承诺中返回这个,但是返回undefined Here is what I have so far? 这是我到目前为止的情况? Is there a better way to approach this? 有没有更好的方法来解决这个问题?

dataService: DataService的:

function getSearchData() {
    return {
        loadDataFromUrls: function () {
            var apiList = ["abo", "ser", "vol", "con", "giv", "blo", "par"];
            var deferred = $q.defer();
            var log = [];
            angular.forEach(apiList, function (item, key) {
                var logNew = [];
                $http({
                    method: 'GET',
                    url: '/api/' + item
                }).then(function (response) {
                    angular.forEach(response.data, function (item, key) {
                        this.push(item);
                    }, logNew);
                    return logNew;
                });
                this.push(logNew);
            }, log);
            $q.all(log).then(

            function (results) {
                deferred.resolve(
                JSON.stringify(results))
            },

            function (errors) {
                deferred.reject(errors);
            },

            function (updates) {
                deferred.update(updates);
            });
            return deferred.promise;
        }
    };
};

Controller: 控制器:

function getSearchData(){
  return dataService.getSearchData.loadDataFromUrls;
}  

$scope.searchData = getSearchData();

$q.all and a map function are what you need here: 您需要$q.allmap功能:

function getSearchData() {
    return {
        // returns a promise for an object like:
        // { abo: resultFromAbo, ser: resultFromSer, ... }
        loadDataFromUrls: function () {
            var apiList = ["abo", "ser", "vol", "con", "giv", "blo", "par"];

            return $q.all(apiList.map(function (item) {
                return $http({
                    method: 'GET',
                    url: '/api/' + item
                });
            }))
            .then(function (results) {
                var resultObj = {};
                results.forEach(function (val, i) {
                    resultObj[apiList[i]] = val.data;
                });
                return resultObj;        
            });
        }
    };
}

If you have an arbitrary set of api calls I would do something like this: 如果你有一组任意api调用,我会做这样的事情:

function getSearchData(){
    var deferred = $q.defer();
    var noOfCalls = apiList.length;
    var results = [];
    var called = 0;

    angular.forEach(apiList, function(item, key) {
        $http.get(url).then(function(result){
           results.push(result);
           called++;
           if(called == noOfCalls){
              deferred.resolve(results);
           }     
        })
   });

    return deferred.promise;
}

However if you know what each api call represents its better to use $.all in this way 但是,如果您知道每个api调用代表什么,那么以这种方式使用$ .all会更好

function search1(){
      return $http.get(search1Url).then(function(result){
          // do something to it
          return result; 
      });
}

function search2(){
      return $http.get(search2Url).then(function(result){
          // do something to it
          return result; 
      });
}

function search3(){
      return $http.get(search3Url).then(function(result){
          // do something to it
          return result; 
      });
}

function search4(){
      return $http.get(search4Url).then(function(result){
          // do something to it
          return result; 
      });
}

function getSearchResult(){

    return $q.all([search1(), search2(), search3(), search4()]).then(function(results){
       // OPTIONAL  aggregate results before resolving
       return results;
    });
}

You should add a list of promises in $q ( not resolved promises like in your code ) , which is a $promise service 你应该在$q添加一个promises列表(在代码中没有解析的promises),这是一个$promise service

Example: 例:

var firstPromise = service1.getMethod1().$promise;
var secondPromise = service2.getMethod2().$promise;
$q.all([firstPromise, secondPromise]).then(function(dataList){
     // dataList[0] will be result of `firstPromise`
     // dataList[1] will be result of `secondPromise`
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM