对异步调用的承诺进行递归

时间:2018-12-15 17:20:51

标签: javascript recursion ecmascript-6 promise

我正在使用用作数据源的外部api。该api基于类似分页的类型将其数据返回。

所以我可以获取第1、2、3等页的数据。但是我遇到的问题是我一次需要所有数据,api不支持此数据,所以我自己编写。

我已经设置了实际的呼叫代码:

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

上面的代码以给定的限制向我返回了预期的结果。另外,当这个数字超过40时,我会得到一个号码(result.total_transactions),我需要用40作为开始等再次拨打电话。

我需要将其组合的代码:

 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({

                })
            });

        })
    }

因此,我首先使用getTransactionPart(0)进行了调用,之后方法本身需要将所有子调用的结果组合在一起,并按预期返回整个结果。我该如何使用递归和Promise?

1 个答案:

答案 0 :(得分:3)

如果您使用async函数和await请求,则这样会更容易:

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

可以肯定,您也可以递归执行此操作,但是您真的需要吗?

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

  return transactions.concat(await getTransactions(start + 40));
}