如果以下代码中的err.retryable = true,我如何更改逻辑以重试:
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) {
//...
})
答案 0 :(得分:3)
除了dfsq为你的回调命名并以异步递归方式使用它的建议之外,另请参阅Caolan McMahon的async.retry模块中的async。例如:
async.retry(3, apiMethod, function(err, result) {
// do something with the result
});
更复杂的例子:
async.auto(
{
users: api.getUsers.bind(api),
payments: async.retry(3, api.getPayments.bind(api))
}, function(err, results) {
// do something with the results
}
);
更多详情in the docs。
我编写了一个实用程序函数,您可以使用该函数使原始方法支持任意数量的重试(err.retryable
支持)。
你可以这样使用它:
var retryingFunction = withRetries(sqs, sqs.getQueueUrl);
(请注意,您需要提供 sqs
和 sqs.getQueueUrl
)
现在您可以像使用retryingFunction
一样使用sqs.getQueueUrl
,但可以使用多次重试作为第一个参数。只有在err.retryable
为真时才会重试。
现在,而不是:
sqs.getQueueUrl({'QueueName': queue.queue}, function (err, qurl) {
// ...
});
你可以使用:
retryingFunction(3, {'QueueName': queue.queue}, function (err, qurl) {
// ...
});
其中3是重试次数。
这是我为使上述成功而写的功能:
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;
}
请参阅此LIVE DEMO进行播放,了解其工作原理。
它在演示中运行良好,我希望它也适用于您的代码。
答案 1 :(得分:1)
您可以为队列回调命名,并在重试请求中再次提供。试试这个:
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) {
//...
});