最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Retry an async function if the error is retryable - Stack Overflow

programmeradmin0浏览0评论

How can I change my logic to retry if the err.retryable = true in the following code:

async.each(queues, function (queue, callback) {
    sqs.getQueueUrl({'QueueName': queue.queue}, function (err, qurl) {
        if (err) {
            if (err.retryable) {
                // How to retry  sqs.getQueueUrl({'QueueName': queue.queue}...?
            } else {
                console.error(err, err.stack);
                callback(err);
            }
        }else{
            //Do lots of things here
        }        

    })
}, function (err) {
    //...
})

How can I change my logic to retry if the err.retryable = true in the following code:

async.each(queues, function (queue, callback) {
    sqs.getQueueUrl({'QueueName': queue.queue}, function (err, qurl) {
        if (err) {
            if (err.retryable) {
                // How to retry  sqs.getQueueUrl({'QueueName': queue.queue}...?
            } else {
                console.error(err, err.stack);
                callback(err);
            }
        }else{
            //Do lots of things here
        }        

    })
}, function (err) {
    //...
})
Share Improve this question asked Dec 22, 2014 at 20:58 user3421904user3421904
Add a ment  | 

2 Answers 2

Reset to default 3

In addition to the advice by dfsq to name your callback and use it an asynchronously recursive manner, see also async.retry from the async module by Caolan McMahon. Example:

async.retry(3, apiMethod, function(err, result) {
    // do something with the result
});

More plex example:

async.auto(
  {
    users: api.getUsers.bind(api),
    payments: async.retry(3, api.getPayments.bind(api))
  }, function(err, results) {
    // do something with the results
  }
);

More details in the docs.

UPDATE

A better solution for your use case:

I wrote a utility function that you can use to make your original method support any number of retries (with err.retryable support).

You can use it this way:

var retryingFunction = withRetries(sqs, sqs.getQueueUrl);

(Note that you need to provide both sqs and sqs.getQueueUrl)

And now you can use the retryingFunction just like you would use sqs.getQueueUrl but with a number of retries as the first arguments. The retries will only be done when err.retryable is true.

So now, instead of:

sqs.getQueueUrl({'QueueName': queue.queue}, function (err, qurl) {
  // ...
});

you can use:

retryingFunction(3, {'QueueName': queue.queue}, function (err, qurl) {
  // ...
});

where 3 is the number of retries.

And this is the function that I wrote to make the above possible:

function withRetries(obj, method) {
  if (!method) {
    method = obj;
    obj = null;
  }
  if (typeof method != "function") {
    throw "Bad arguments to function withRetries";
  }
  var retFunc = function() {
    var args = Array.prototype.slice.call(arguments);
    var retries = args.shift();
    var callback = args.pop();
    if (typeof retries != "number" || typeof callback != "function") {
      throw "Bad arguments to function returned by withRetries";
    }
    var retryCallback = function (err, result) {
      if (err && err.retryable && retries > 0) {
        retries--;
        method.apply(obj, args);
      } else {
        callback(err, result);
      }
    };
    args.push(retryCallback);
    method.apply(obj, args);
  };
  return retFunc;
}

See this LIVE DEMO to play with it and see how it works.

It works fine in the demo, I hope it will also work for your code.

You can give queue callback a name and provide it in retry request again. Try this:

async.each(queues, function (queue, callback) {
    sqs.getQueueUrl({'QueueName': queue.queue}, function queueCallback(err, qurl) {
        if (err) {
            if (err.retryable) {
                sqs.getQueueUrl({'QueueName': queue.queue}, queueCallback);
            } else {
                console.error(err, err.stack);
                callback(err);
            }
        } else {
            //Do lots of things here
        }
    });
}, function (err) {
    //...
});
发布评论

评论列表(0)

  1. 暂无评论