2016-11-18 35 views
1

我的項目是基於反應,終極版,終極版,傳奇,ES6,我試圖從這個API獲取數據:如何在多個頁面上獲取數據?

http://api.dhsprogram.com/rest/dhs/data/BD,2000,2004,2007?&returnFields=CharacteristicLabel,Indicator,IndicatorId,Value&f=json

正如你所看到的,這個特定的API調用顯示數據用的限制每頁100個數據分佈在40頁上。

根據這個回答: http://userforum.dhsprogram.com/index.php?t=msg&th=2086&goto=9591&S=Google 它說你可以擴展到每頁最多3000個數據的限制。

然而,在某些情況下,我會做超出該限額,這意味着我不會接受我的所有數據做一個這樣的API調用:

export function fetchMetaData(countryCode: string, surveyYears: string) { 
return (fetch('http://api.dhsprogram.com/rest/dhs/data/' + countryCode + ',' + surveyYears + '?returnFields=CharacteristicLabel,Indicator,IndicatorId,Value&f=json') 
    .then(response => response.json()) 
    .then(json => json.Data.map(survey => survey))) 
} 

所以我的問題是;鑑於我知道數據的總頁數,從API獲取所有數據的最佳方式是什麼。論壇鏈接中的答案建議循環訪問API。但是,我無法找到正確的語法用法來執行此操作。

我的想法是做一個API調用來獲得總頁數。然後使用redux + redux-saga將其存儲在狀態中。然後做一個新的請求發送總頁數作爲參數並獲取這個總頁數次。通過這樣做,我無法弄清楚爲每次迭代存儲數據的語法。

+0

有幾個問題:1.爲什麼您需要在redux商店中保存總頁數?您可能不想將所有數據封裝到一個操作中(使用多個異步提取)。 2.你更可能的意思是「......將起始頁作爲參數發送......」,對吧? 3.你的問題具體是什麼,到目前爲止你嘗試了什麼?迭代數組?彙總?處理幾個異步呼叫或承諾? – matthias

+0

1.在redux商店中存儲頁面總數只是對我自己的問題的一個建議,您提出的建議聽起來更符合邏輯。 2.正確。 3.到目前爲止我所做的是使用redux-saga來處理異步提取。當我的組件通過調用一個動作請求數據時,我的觀察者在傳奇中接收到來自上述函數的動作並請求數據。我收到的是我存儲在操作主體中的1頁數據,並將其添加到我的減速器中。我的問題是,我無法使用上述功能從每個頁面獲取所有數據。有沒有一個聰明的方法來做到這一點? @matthias –

+0

好的,我們正在接近這一點。我從來沒有使用過redux-saga,也不知道這個lib是否提供了一個專門的和首選的方法來解決這個問題。但我認爲這不應該阻止你以典型的方式使用承諾(或異步/等待)和處理構建/映射數組和對象的函數來解決問題。如果我對你有所瞭解,你正在尋找一種方法來執行對一個API的多個異步調用,彙總所收集的數據,然後將其交給store/reducer以創建新狀態。請問:你對JavaScript一般有多熟悉? – matthias

回答

4

一個可能的解決方案 - 想法是首先獲取頁面的數量,然後進行適當數量的API調用,將每次調用的承諾推送到數組中。然後,我們等待所有的承諾解決,並用返回的數據做一些事情。

function fetchMetaData() { 
    let pagesRequired = 0; 

    fetch('apiUrlToGetPageNumber') 
    .then(resp = > { 
     const apiPromises = []; 
     pagesRequired = resp.data.pagesRequired; 

     for (let i=pagesRequired; i>0;i--) { 
      apiPromises.push(fetch('apiUrlToSpecificPage?page = ' + i)); 
     } 

     Promise.all(apiPromises) 
     .then(responses => { 
      const processedResponses = []; 
      responses.map(response => { 
       processedResponses.push(response); 
      } 

      // do something with processedResponses here 
     }); 
    } 
} 
+0

非常感謝!(我upvoted答案,但我有少於15rep)。但是,通過在processedResponses上使用.reduce;該函數可以回想起prev被定義。但我明白了,所以我會試着弄明白! –

+0

減少的好處,我會編輯成有用的東西。 –

+0

我將不勝感激=) –

0

這裏是另一種可能的解決方案,使用async/await。這很漂亮,total_pages計數是動態的,所以如果它在處理請求時增加,它會確保你完成所有工作。

async function fetchMetaData() { 
    let allData = []; 
    let morePagesAvailable = true; 
    let currentPage = 0; 

    while(morePagesAvailable) { 
    currentPage++; 
    const response = await fetch(`http://api.dhsprogram.com/rest/dhs/data?page=${currentPage}`) 
    let { data, total_pages } = await response.json(); 
    data.forEach(e => allData.unshift(e)); 
    morePagesAvailable = currentPage < total_pages; 
    } 

    return allData; 
} 
相關問題