2017-08-07 24 views
1

我需要閱讀的API,只給每個查詢100個結果,並從那裏獲得下一個100如何在Node.js中對promise做遞歸請求?

我已經成功地做多個請求先後與下面的代碼時間戳的數據,但對於一些它永遠不會回到最初的承諾。它陷入了「沒有更多的訂單來獲取」。

app.get('/test', (req, res) => { 

    const getOrders = (from) => { 
    return request(mcfApiUrl + "changes?created_after_ts="+from+"&key="+mcfKey) 
    .then(xml => convert.xmlDataToJSON(xml,{explicitArray:false,mergeAttrs:true})) 
    .then(orders => checkForMore(orders)); 
    } 

    const checkForMore = (orders) => { 
    return new Promise((resolve, reject) => { 
     if (orders['Orders']['orders'] == 100){ 
     getOrders(orders['Orders']['time_to']); 
     console.log("Fetched "+ orders['Orders']['orders']+" orders"); 
     console.log("More orders available from: "+moment(orders['Orders']['time_to']*1000).format()); 
     } 
     else { 
     console.log("Fetched "+ orders['Orders']['orders']+" orders"); 
     console.log("No more orders to fetch"); 
     resolve(orders); 
     } 
    }); 
    }; 

    var fromdate = 1483999200; 

    getOrders(fromdate) 
    .then(output => res.send("Done")) // It never gets here 
    .catch(err => console.log(err)); 

}); 

我錯過了什麼?

+0

尋找Ajax請求的無限循環? – Hitmands

+1

我建議使用事件發射器或觀察器代替 – MinusFour

+0

@Hitmands:if語句應該使它成爲非無限的。 – Jopi

回答

2

你的問題是,你沒有解決所有選項的checkForMore承諾。

const checkForMore = (orders) => { 
    return new Promise((resolve, reject) => { 
     if (orders['Orders']['orders'] == 100){ 
     getOrders(orders['Orders']['time_to']); // <-- not resolved 
     } 
     else { 
     resolve(orders); 
     } 
    }); 
    }; 

只是包裹在調用getOrdersresolve將解決這個問題。

resolve(getOrders(orders['Orders']['time_to'])) 

但是,你並不真的需要創建一個新的承諾:

const checkForMore = (orders) => 
    orders['Orders']['orders'] == 100 
    ? getOrders(orders['Orders']['time_to']) 
    : Promise.resolve(orders); 

事實上,你的整個功能可以收縮成幾行:

const getOrders = (from) => 
    request(mcfApiUrl + "changes?created_after_ts="+from+"&key="+mcfKey) 
    .then(xml => convert.xmlDataToJSON(xml,{explicitArray:false,mergeAttrs:true})) 
    .then(orders => 
     orders.Orders.orders == 100 
     ? getOrders(orders.Orders.time_to) 
     : Promise.resolve(orders) 
    ); 

現在,如果你想積累所有的訂單,你需要通過遞歸級別保持一些狀態。

你可以做,要麼用全局狀態或其它參數:

const getOrders = (from, allOrders = []) => 
    //     ^accumulation container 
    request(mcfApiUrl + "changes?created_after_ts="+from+"&key="+mcfKey) 
    .then(xml => convert.xmlDataToJSON(xml,{explicitArray:false,mergeAttrs:true})) 
    .then(orders => { 
     allOrders.push(orders); // <-- accumulate 
     return orders.Orders.orders == 100 
     ? getOrders(orders.Orders.time_to, allOrders) // <-- pass through recursion 
     : Promise.resolve(allOrders) 
    }); 
+0

謝謝!解決方案(getOrders(orders ['Orders'] ['time_to']))是缺失的部分! :) – Jopi

+0

@Jopi很高興幫助:) – nem035