2

I am using an external api that I use as my datasource. That api gives its data back based on a pagination like type.

So I can get data for page 1, 2, 3 etc. But the problem that I have is that I need all data at once, the api doesn't support this so I write it myself.

I have made the actual call code:

function getTransactionPart(start){
        return new Promise(function(resolve, reject) {

            const options = {
                url: 'myurl?limit=40&start='+start,
                json: true
            };

            let result = {total_transactions : 0, transactions : []};

            request(options, function (error, response, body) {

                if (error) {
                    return reject(result);
                }

                body.data.forEach(function (transaction) {
                        result.transactions.push({
                            timestamp: transaction.timestamp,
                            amount: transaction.amount,
                            confirmed: transaction.confirmed
                        });
                });

                result.total_transactions = body.total

                return resolve(result);
            })
        })
    }

The above code returns me the expected results with the limit that I gave. Also I get a number back (result.total_transactions) when this is more than 40 I need to make another call with 40 as start etc etc.

The code where I need to combine it:

 function getTransactions(start) {
        return new Promise(function(resolve, reject) {

            getTransactionPart(start).then(result => {
                if(result.total_transactions > 40) {
                    //next call
                } else {
                    // return all?
                }
                console.log(result)
            }).catch(error => {
                console.error(error);
                return r.json({

                })
            });

        })
    }

So I do the first call with getTransactionPart(0) after that the method itself needs to combine the result form all the sub calls and return the whole result as expected. How can I do this with recursion and promises?

da1lbi3
  • 4,369
  • 6
  • 31
  • 65
  • This is a perfect fit for [anamorphisms](https://stackoverflow.com/a/50121218/633183) – Mulan Dec 15 '18 at 19:40
  • Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi Dec 15 '18 at 20:06

1 Answers1

3

This is easier if you use an async function and await the request:

  async function getTransactions(start) {
    const result = [];
    for(let pos = start; ; pos += 40) {
      const { total_transactions, transactions } = await getTransactionPart(pos);
      result.push(...transactions);

      if(total_transactions < 40) break;
    }
    return result;
 }

For sure you could also do this recursively, but do you really need that?

async function getTransactions(start) {
  const { total_transactions, transactions } = await getTransactionPart(pos);
  if(total_transactions < 40) 
     return transactions;

  return transactions.concat(await getTransactions(start + 40));
}
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151