如何处理节点中的递归回调?

时间:2016-10-14 16:32:05

标签: javascript node.js recursion callback

我正在使用Robinhood-node API来检索我的安全产品组合。 API有两个我使用的功能 -

orders(callbackfn)

检索最后100个订单和指向下一页的链接。

url(url,callback)

要获得另外100个订单的下一页。

这两个函数都返回一个看起来像 -

的JSON
{
    results:[
        {order 0},
        {order -1},
        ...
        {order -100}],
    next: url_for_next_page
}

现在,我需要将下一个url传递给url函数以获得另外100个订单。最后一页有next: null

在处理url的结果之前,无法调用orders。在处理之前的url结果之前,无法调用后续网址。这导致我创建了一个回调地狱:-( order - > url - > url - > url ...

我无法在循环中调用url方法。循环在回调执行之前继续执行。

如何反复拨打url?到目前为止,我使用递归函数调用来管理hack。这是我的代码 - https://gist.github.com/lordloh/f5c8c589b4538ab9674db919ae2e2834

我正在学习节点js ...: - /

2 个答案:

答案 0 :(得分:1)

您是否考虑过使用Promises来避免回调地狱?

我查看了您的代码,我想象使用Promises

这样的内容
const credentials = {
    username: 'username',
    password: 'Password'
};

const Robinhood = require('../robinhood-node/src/robinhood');

function orderHandler(orderArray,allOs){
    return new Promise((resolve, reject) => 
    {       
        for (let i = 0; i < orderArray.length; i++) {
            var e = orderArray[i];
            var ss = e.instrument.split('/');
            var instrument = ss[ss.length-2];
            allOs.push({'id':e.id,
              'instrument':instrument,
              'quantity':e.quantity,
              'price':e.average_price,
              'side':e.side,
              'transaction_time':e.last_transaction_at
            });
        }
        resolve(allOs);     
    });
}

Robinhood(credentials, () => 
{
  Robinhood.orders(function(e,r,b){   
    orderHandler(b.results,[]).then((allOs) => 
    {
        urlSequence(b.next, allOs).then((allOS) => csv(allOs));             
    });
  });       
});

function urlSequence(url,allOs){
    if(!url)
        return Promise.resolve(allOS);

    return new Promise((resolve, reject) =>
    {
        Robinhood.url(url, (e,r,b) => 
        {
            orderHandler(b.results, allOS)
                .then((allOs) => {
                    setTimeout(() => resolve(urlSequence(b.next, allOs)), 0);                       
                });     
        });     
    });
}

function csv(Arr){
    var A;
    for (var i=0;i<Arr.length;i++){
        A=Arr[i];
        console.log(A.id+", "+A.instrument+", "+A.quantity+", "+A.price+", "+A.quantity+", "+A.side+", "+A.transaction_time);
    }
}

答案 1 :(得分:0)

嗯,我们假设我们有一个名为fetch的函数,它只是获取一些数据并将其传递给回调,这就是它的完成方式:

function getAllPages(url, callback) {
  // This is a function that returns a function:
  const getPage = (oldData) => (response) => {
    // We concat the data from the response to our collected list:
    const newData = oldData.concat(response.results)

    if(response.next && response.next.length) {
      // Call the function returned by getPage passing in newData
      // This is what we call recursion
      fetch(response.next, getPage(newData))
    } else {
      // If there is no next page we just pass all the collected data to a callback:
      callback(newData)
    }
  }

  // We pass it an empty list as initial data:
  getPage([])({next: url, results: []})
}

getAllPages('some url...', (data) => {
  console.log(data)
})

我希望这会帮助你开始。

如果页面太多,您可以使用setTimeout轻松添加一些限制或设置限制。