2015-03-20 2 views
6

Я работаю над вызовом $ http, который пересекает каждый из нескольких api и возвращает все данные в одном объекте. У меня обычно есть обещание, готовое к разрешению, когда был получен вызов $ http. Подобно этому:

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

Текущая функция У меня есть петли над каждым апи и помещает каждый объект в апи в массив, а затем толкает его в общий массив. У меня было это функционирование, возвращая многомерный массив, который нужно было сгладить.

Я хотел бы вернуть это в обещание, но возвращаю undefined. Вот что у меня есть до сих пор? Есть ли лучший способ приблизиться к этому?

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

Контроллер:

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

$scope.searchData = getSearchData(); 
+1

Я не 100% уверен, что здесь происходит - вы не толкать пустые массивы ('logNew') в массив' log', который вы хотите подождать? Если вы не будете нажимать 'обещание', возвращенное' $ http' вместо этого? –

ответ

16

$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;   
      }); 
     } 
    }; 
} 
+0

По какой-то причине я возвращаюсь в контроллер неопределенным: function getSearchData() { return dataService.getSearchData.loadDataFromUrls; } console.log (getSearchData()); – byrdr

+0

@byrdr Это потому, что 'getSearchData' возвращает объект с' loadDataFromUrls' как одно из своих свойств, но вы получаете доступ к 'loadDataFromUrls' как свойство' getSearchData'. Попробуйте: 'function getSearchData() {return dataService.getSearchData(). LoadDataFromUrls; } console.log (getSearchData()); 'Это оставляет вопрос о том, почему у вас есть дополнительный уровень между вашей службой данных и функцией' getSearchData'. – JLRishe

+0

Это имеет смысл, спасибо. Вышеприведенный код в настоящее время регистрирует сама функция. – byrdr

0

Вы должны добавить список обещаний в $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` 
}); 
1

Если у вас есть произвольный набор 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; 
} 

Однако, если вы знаете, что представляет собой каждый апи вызов его лучше использовать $ .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; 
    }); 
} 
+0

Вы имели в виду '$ q.defer()'? – GregL

+0

[Что такое отложенный антипаттерн и как его избежать?] (Http://stackoverflow.com/questions/23803743/what-is-the-deferred-antipattern-and-how-do-i-avoid-it) – JLRishe

+0

да .. спасибо за то, что заметили мою ошибку :) –

Смежные вопросы