处理递归承诺中的异常

时间:2017-03-08 23:47:03

标签: node.js recursion promise

我试图能够处理分页API,并且如果针对太多请求进行限制,则会重试。如果' nextToken'则通过递归来处理分页。存在于响应对象中。我希望能够捕获一个Throttling Exception,并通过递归有效地启动整个请求而不传递令牌。这是我目前的代码:

function getAllExecHist(execArn) {
  var sfn = new AWS.StepFunctions();
  sfn = Promise.promisifyAll(sfn); 
  execHists = [];
  return new Promise(function(resolve, reject) {
    function getExecHist(nextToken) {
      params = {};
      params.executionArn = execArn;
      if (nextToken !== undefined) {
        params.nextToken = nextToken;
      }
      sfn.getExecutionHistoryAsync(params)
        .then(function(results) {
          execHists = execHists.concat(results.events);
          if (!results.nextToken) {
            resolve(execHists);
          }
          else {
            getExecHist(results.nextToken);
          }
        })
        .catch(function(e) {
          console.log('caught this: ', e);
          console.log('retrying');
          return new Promise(function(res, rej) {
          console.log('Sleeping');
          setTimeout(function() {
            execHists = [];
            res(getExecHist()); 
          }, random(100,10000));
          });         
        })
    }
    getExecHist();
  });
}

递归正在处理分页而没有问题,但是因为添加catch,它就永远不会返回。我有什么想法,我做错了什么/怎么解决?

1 个答案:

答案 0 :(得分:1)

AWS SDK supports promises,您可以将Bluebird配置为其承诺库。

const Promise = require('bluebird');
const AWS = require('aws');
AWS.config.setPromisesDependency(Promise);
const sfn = new AWS.StepFunctions();

使用Promise.delay()代替setTimeout

如果函数已经返回它们,请尝试并避免创建新的promise。如果您有大量可能引发错误的同步代码或需要尽早解决承诺,则仅在new Promise中包含承诺。

以下内容还通过在函数调用之间传递值来避免额外函数和嵌套作用域。

function getExecHist(execArn, execHists, nextToken) {
  let params = {};
  params.executionArn = execArn;
  if ( nextToken !== undefined ) params.nextToken = nextToken;
  if ( execHists === undefined ) execHists = [];
  return sfn.getExecutionHistory(params).promise()
    .then(results => {
      execHists = execHists.concat(results.events);
      if (!results.nextToken) return execHists;
      return getExecHist(execArn, execHists, results.nextToken);
    })
    .catch(e => {
      console.log('caught this: ', e);
      console.log('retrying');
      return Promise.delay(random(100,10000))
        .then(() => getExecHist(execArn));
    })
}

最终,您应该具体说明您重试的错误,并包括计数或时间限制。

另请注意,这是重试速率限制问题的错误方法,因为这会从头开始。速率限制重试应该从它停止的地方继续,否则您只是增加了速率限制问题。