我有一种非通用的方法,可以通过指数回退重试到Internet的呼叫。我正在尝试以一种通用的方式来实现它,到目前为止,我的工作方式只有一半有效。
全部要旨
如下所示的两种实现方法与我几乎相同,甚至每次 request.get 成功时都可以使用。
但是,当 request.get 随机抛出错误时,重试逻辑的工作方式将有所不同。使用第一种非泛型方法,一切都会按预期工作,重试呼叫直到成功或重试 ==0。使用第二种非泛型方法,重试逻辑反复触发直到 retries < / em> ==0。它不会第二次,第三次,第四次等向互联网发出呼叫。有什么作用?
我了解所有这些信息,因为我在自己的控制下进行了模拟 request.get()方法的测试,并以正确的响应或错误返回。
工作方法
好的,所以我有这样的工作递归重试逻辑,如下所示:
function getPageOfThreadsWithRetry(access_token, nextPageToken, retries, delay) {
return new Promise((resolve, reject) => {
getPageOfThreads(access_token, nextPageToken).then((results) => {
resolve(results);
}).catch((err) => {
if (retries == 0) {
reject(err);
} else {
let retry = function() {
retries--;
delay = delay * DELAY_MULTIPLIER;
resolve(getPageOfThreadsWithRetry(access_token, nextPageToken, retries, delay));
}
setTimeout(retry, delay);
}
});
});
getPageOfThreads(access_token,nextPageToken)是一个简单的函数,它返回一个包装了 request.get()调用的promise,并在成功的情况下进行解析,并在失败时拒绝错误的情况。
function getPageOfThreads(access_token, pageToken) {
return new Promise((resolve, reject) => {
let options = createOptions(access_token, pageToken);
request.get(options, (error, response, body) => {
if (!error && response.statusCode == 200) {
body = JSON.parse(body);
resolve(body)
} else {
reject(error);
}
});
});
}
从工作递归异步函数内部调用getPageOfThreadsWithRetry(...),该函数将一直调用直到没有 nextPageToken 为止。呼叫看起来像:
let delay = INIT_RETRY_DELAY;
let retries = MAX_RETRIES;
let response = await getPageOfThreadsWithRetry(access_token, nextPageToken, retries, delay).catch((error) => {
});
这按预期工作,调用 getPageOfThreads()并一次又一次地返回 response 对象,直到没有nextPageToken。 如果错误被随机抛出在某个地方,它会以指数回退的方式重试该呼叫,直到它成功或尝试了超过 try 次。
半工作方法
我想在我的应用程序的许多地方实现这种功能。因此,我试图提出一个通用的实用程序函数来完成此任务。到目前为止,我已经提出了这一点(在这种情况下,prms == promise):
function retryPromise(prms, retries, delay, delayMultiplier) {
return new Promise((resolve, reject) => {
prms.then((results) => {
resolve(results);
}).catch((err) => {
if (retries == 0) {
reject(err);
} else {
let retryFunc = function() {
retries--;
delay = delay * delayMultiplier;
resolve(retryPromise(prms, retries, delay, delayMultiplier));
}
setTimeout(retryFunc, delay);
}
});
});
}
尝试这样称呼它:
function getPageOfThreadsWithRetry(access_token, nextPageToken) {
let delay = INIT_RETRY_DELAY;
let retries = MAX_RETRIES;
let delayMultiplier = DELAY_MULTIPLIER;
let prms = getPageOfThreads(access_token, nextPageToken);
return retryPromise(prms, retries, delay, delayMultiplier);
}
并以与以前类似的方式从上方调用 getPageOfThreadsWithRetry()
let response = await getPageOfThreadsWithRetry(access_token, nextPageToken).catch((err) => {
});
第二种方法对我来说比较理想,因为它可以在我接到互联网的任何地方实施,并提取所有代码的详细信息,这些代码取决于互联网的响应。
我知道这是一个相当复杂的问题,所以我真的很感谢愿意提供一些思想和时间的人,尤其是那些可能有答案的人?
即使您的答案涉及一种完全不同的方法,我也想学习您可能知道的东西。
-谢谢您的时间
答案 0 :(得分:0)
在第一个方法中,在递归函数request.get
中调用getPageOfThreadsWithRetry
。但是在第二种方法中,request.get
在递归函数retryPromise
之外被调用。
我建议您将retryPromise
签名更改为类似
function retryPromise(promiseCreator, retries, delay, delayMultiplier) {
return new Promise((resolve, reject) => {
promiseCreator()
.then(resolve)
.catch((err) => {
if (retries == 0) {
reject(err);
} else {
let retryFunc = function() {
retries--;
delay = delay * delayMultiplier;
resolve(retryPromise(promiseCreator, retries, delay, delayMultiplier));
}
setTimeout(retryFunc, delay);
}
});
});
}
并像使用它
function getPageOfThreadsWithRetry(access_token, nextPageToken) {
let promiseCreator = () => getPageOfThreads(access_token, nextPageToken);
return retryPromise(promiseCreator, retries, delay, delayMultiplier);
}