我需要从API中读取数据,每个查询只能提供100个结果,以及从下一步获取100个结果的时间戳。
我已经设法使用下面的代码一个接一个地执行多个请求,但由于某种原因它永远不会返回到原始的承诺。它被困在“没有更多的订单来取回”。
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 :(得分:3)
您的问题是您没有解决所有选项的checkForMore
承诺。
const checkForMore = (orders) => {
return new Promise((resolve, reject) => {
if (orders['Orders']['orders'] == 100){
getOrders(orders['Orders']['time_to']); // <-- not resolved
}
else {
resolve(orders);
}
});
};
只需将getOrders
与resolve
一起打包即可解决问题。
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)
});