【问题标题】:How to do recursive requests to an API with promise in Node.js?如何在 Node.js 中使用 promise 对 API 进行递归请求?
【发布时间】:2018-01-15 01:12:46
【问题描述】:

我需要从 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));

});

我错过了什么?

【问题讨论】:

  • 寻找无限循环的 ajax 请求?
  • 我建议使用事件发射器或可观察对象
  • @Hitmands: if 语句应该使它成为非无限的。
  • @MinusFour:我也对其他解决方案持开放态度。我只是认为我的解决方案会很简单(如果可行的话......)
  • 您没有在if() 中解析...试试resolve( getOrders(orders['Orders']['time_to']))

标签: javascript node.js express promise


【解决方案1】:

您的问题是您没有解决所有选项的 checkForMore 承诺。

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

只需用resolve 包装对getOrders 的调用即可解决此问题。

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

但是,您实际上并不需要创建新的 Promise:

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

【讨论】:

  • 谢谢! resolve(getOrders(orders['Orders']['time_to'])) 是缺失的部分! :)
  • @Jopi 很高兴为您提供帮助 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-08
  • 2021-02-03
  • 2018-06-29
  • 1970-01-01
  • 1970-01-01
  • 2019-05-16
  • 2018-06-10
相关资源
最近更新 更多