Angularjs Angular$q返回多个$http调用

Angularjs Angular$q返回多个$http调用,angularjs,angular-promise,Angularjs,Angular Promise,我正在处理一个$http调用,该调用在多个api上循环,并返回一个对象中的所有数据。我通常会在$http调用完成后准备好解决承诺。与此类似: function getAllData(api) { return $http({ method: 'GET', url: '/api/' + api }) .then(sendResponseData) .catch (sendGetVolunteerError); } 当前函数在每个ap

我正在处理一个$http调用,该调用在多个api上循环,并返回一个对象中的所有数据。我通常会在$http调用完成后准备好解决承诺。与此类似:

function getAllData(api) {
    return $http({
        method: 'GET',
        url: '/api/' + api
    })
    .then(sendResponseData)
    .catch (sendGetVolunteerError);
}
当前函数在每个api上循环,将api中的每个对象推送到一个数组中,然后将其推送到一个整体数组中。我有这个功能,返回一个多维数组,需要将其展平

我希望以承诺的形式返回此内容,但我返回未定义的
。这是我到目前为止得到的?有没有更好的办法

数据服务:

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;
        }
    };
};
控制器:

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

$scope.searchData = getSearchData();

您应该在
$q
中添加一个承诺列表(与您的代码中的承诺不一样),这是一个
$promise service

例如:

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

如果您有一组任意的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;
}
但是,如果您知道每个api调用代表什么,那么最好以这种方式使用$

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

$q.all
map
功能是您在此需要的:

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

我不能100%确定这里发生了什么-您是否正在将空数组(
logNew
)推送到要等待的
log
数组?您不应该转而推动
$http
返回的
承诺吗?您的意思是
$q.defer()
?@JLRishe感谢您指出反模式。。我今天学到了一些东西。。干杯Chris@Chris很乐意帮忙。您仍然在
getSearchResult
中使用它,您需要传递给
$q。这里所有的
search1()
search2()
等等,而不仅仅是
search1
search2
。您的其他函数需要
return
语句,因为它们不返回任何内容。您在
getSearchResult
中还有一个额外的return语句,但这里有一个upvote:)出于某种原因,我在控制器中返回未定义的:函数getSearchData(){return dataService.getSearchData.loadDataFromUrls;}console.log(getSearchData())@byrdr这是因为
getSearchData
返回的对象的属性之一是
loadDataFromUrls
,但您正在访问
loadDataFromUrls
作为
getSearchData
的属性。尝试:
函数getSearchData(){return dataService.getSearchData().loadDataFromUrls;}控制台.log(getSearchData())
这就留下了一个问题,为什么在数据服务和
getSearchData
函数之间有一个额外的层。这很有意义,谢谢。上面的代码当前记录函数本身。将其包装在iffe中会返回一个承诺对象{then:function,catch:function,finally:function}@byrdr是的,您需要另一对括号来实际调用它:
console.log(getSearchData())。但我认为你涉及的功能层次太多了。您只需执行以下操作:
var getSearchData=dataService.getSearchData().loadDataFromUrls;log(getSerachData())。这应该是一个承诺。