2017-08-03 101 views
0

我在Javascript和AngularJS一個初學者,我試圖做如下:AngularJS - 通過異步GET循環請求

有接受一個列表,網址爲輸入,找到在當地各自的數據服務緩存/存儲庫自定義服務。

  • 如果全部找到,則返回。
  • 如果缺少某些內容,則通過對API進行ASYNC調用來獲取缺少的內容。它們也存儲在存儲庫中以備將來使用。

所有接收到的數據都連接成一個本地「數據」變量,並作爲一個單一的對象數組發送到控制器。

它使用$ .map循環訪問每個URL以獲取數據並將其連接到本地「數據」變量。循環完成後,它將返回「數據」變量。

我知道這不起作用,也是它的原因。但是,我無法弄清楚如何使用ASYNC設計模式來實現這一點。

myService.factory("dataManagerService",["dataRepositoryService","dataFetchService", 
    function(dataRepositoryService,dataFetchService) 
    { 
     var methodObj = {}; 

     methodObj.getObjData = function(urlList) 
     { 
      //URLs are used to fetch data from API and also to uniquely identify the fetched data. 
      //urlList is a list/array of URLs for which data is required. 

      //Get all objects from data repository which are specified in the URL list. 
      var data = dataRepositoryService.getData(urlList); 

      //If repository did not have all objects specified from the URL list, fetch the missed objects. 
      if (data.length < urlList.length) 
      { 

       //Get list of URL for which data was received from repository. 
       var excludeURLList = $.map(data, 
        function(obj) 
        { 
         return obj.url; 
        } 
       ); 

       //Get list of all URLs from urlList that are missing from excludeURLList 
       var fetchUrlList = $.grep(urlList, 
        function(url) 
        { 
         return excludeURLList.indexOf(url) < 0; 
        } 
       ); 

       //Loop through all URLs in fetchUrlList (for which data was not found in the repository) 
       $.map(fetchUrlList, 
        function(url) 
        { 
         //Make a GET request to the API 
         dataFetchService.fetchData(url) 
         .then(
          function(response) 
          { 
           //Add the received response to the repository, so that its available the next time. 
           dataRepositoryService.setData(response.data); 

           //Append missing data to "data" variable 
           data.concat(response.data); 
          } 
         ); 
        } 
       ); 
      } 
      return data; /* This will be incomplete since it will be returned before all the async calls have been completed. */ 
     } 

     return methodObj; 
    } 
]); 

回答

-1

你會想用$ q.all()來檢索所有網址。下面是關於這一個相當不錯的文章:https://www.martin-brennan.com/using-q-all-to-resolve-multiple-promises/

你會想要做這樣的事情:

getObjectList(urlList) { 
    var promises =[] 
    urlList.map(function(url) { promise.push(getUrl(url) }) 
    $q.all(promises).then(function(responses) { assemble what you want to return here} 
) 


} 

function getUrl(url) { 
    var q=$q.defer() 
    if (whereever you've stored the data has fetched the url already) { 
     return $q.when(the data) 
    } else { 
      return $http.get(url).then(function(response) { 
       return $q.resolve(response.data) 
      }, function (error) { return $q.reject(error) }) 
    } 

} 
+0

感謝沒有任何解釋的downvote。這很有幫助。 –

+0

這對我有效。但是,你能告訴我爲什麼我們在getUrl()方法中使用$ q.defer()嗎?只是$ http的結果本身就是一個承諾,我們需要$ q.all()方法。 –

+0

謝謝。我很高興工作。我使用$ q.defer的唯一原因是我只能返回數據對象,仍然包含在承諾中。如果只返回$ http.get,那麼你會得到一個完整的響應對象。 –