Javascript 无法通过最大重试次数解决承诺问题
在过去的几天里,我一直在与Promise和一个初学者斗争。我必须调用一个外部API并检查是否有响应。如果为null,则再次调用api并进行最大重试尝试,这是可配置的。我尝试了以下方法,但不确定我缺少了什么。这是我做的一个例子 如果数据可用,则显示数据可用。如果不是,则重试一段时间,如果达到零,则使用API中不可用的数据进行解析。如果数据在重试后可用(例如:第二次),则停止并显示响应Javascript 无法通过最大重试次数解决承诺问题,javascript,node.js,promise,es6-promise,Javascript,Node.js,Promise,Es6 Promise,在过去的几天里,我一直在与Promise和一个初学者斗争。我必须调用一个外部API并检查是否有响应。如果为null,则再次调用api并进行最大重试尝试,这是可配置的。我尝试了以下方法,但不确定我缺少了什么。这是我做的一个例子 如果数据可用,则显示数据可用。如果不是,则重试一段时间,如果达到零,则使用API中不可用的数据进行解析。如果数据在重试后可用(例如:第二次),则停止并显示响应 function callExternalAPI(retry, interval) { try { re
function callExternalAPI(retry, interval) {
try {
return new promise((resolve, reject) => {
if(retry <=0 ) {
return resolve("Data not available in API"); // This is not working, request is hanged.
}
return myapiCall().then((response) => {
if(!response) {
// If empty then retry calling api again
return setTimeOut(async () => {
await callExternalAPI(retry - 1, interval)
}, interval);
}
return resolve(response);
})
})
}
} catch((error) => {
reject(error);
})
callExternalAPI(3, 1000).then((rsp) => {
console.log({response: "data available"});
}).catch((error) => {
throw error;
})
函数调用外部LAPI(重试,间隔){
试一试{
返回新承诺((解决、拒绝)=>{
如果(重试){
如果(!响应){
//如果为空,请重试调用api
返回setTimeOut(异步()=>{
等待callExternalAPI(重试-1,间隔)
},间隔);
}
返回解析(响应);
})
})
}
}捕获((错误)=>{
拒绝(错误);
})
调用外部LAPI(31000)。然后((rsp)=>{
log({响应:“数据可用”});
}).catch((错误)=>{
投掷误差;
})
任何帮助都将非常感谢,因为我仍处于学习阶段
提前感谢这样做的一种方法是将两次尝试之间的“等待”打包成一个单独的
async
方法和wait
此方法
然后,只要重试计数未达到0
,如果没有从myapiCall
返回成功结果,只需重复调用callExternalApi
。请注意,在我的示例中,如果达到最大计数,我将抛出一个错误(当然,您可以通过返回undefined/null
等不同方式处理此错误):
异步函数等待(timeInMs){
log('Waiting…');
返回新承诺((resolve=>setTimeout(()=>resolve(),timeInMs));
}
异步函数调用ExternalAPI(尝试次数,超时){
如果(次数){
试一试{
const result=wait callExternalApi(31000);
控制台日志(结果);
}捕捉(错误){
控制台日志(err);
}
})();
我建议使用语法,这允许我们以更容易理解的形式构造代码,一旦我们这样做,创建一个包装函数callExternalAPI就相对简单了,它可以在API调用上循环
每次失败后都会调用wait函数,您可以使它更复杂,每次尝试可能会后退更长的时间,但我们现在将保留一个固定的间隔
//让我们在前几次调用中失败。
设myApiCallCount=0;
//模拟函数来模拟API调用。您可以用真实的API调用替换它。
函数myapiCall(){
如果(++myApiCallCount<3){
返回新承诺((resolve,reject)=>setTimeout(reject,500,新错误(“某些API错误”));
}
返回新的承诺(resolve=>setTimeout(resolve,500,{users:[{name:'user1},{name:'user}]}));
}
函数等待(间隔){
返回新承诺(resolve=>setTimeout(resolve,interval));
}
异步函数调用外部LAPI(apiFunction,attemptCount,interval){
对于(让trunt=1;trunt关于代码的一些注释)。
您的try-catch未正确实现,代码将无法执行。
您没有检查是否有响应
,因为您使用了结果
在这一行中,myapiCall()。然后((响应)=>{if(!result).
它应该是myapiCall()。然后((响应)=>{if(!response)
,尽管您在检查api响应时应该小心,因为例如fetch
不会处理错误,因此在这种情况下,您应该检查响应状态response.status==200
,否则它将始终默认为true,在您的示例中,您也不需要使用setTimeout,您可以只检查响应并如果没有响应,则再次调用该函数。
优化你的代码我相信应该是这样的
i=0
function callExternalAPI(retry, interval) {
return new Promise((resolve, reject) => {
return myapiCall().then((response) => {
if (response) return response //if you are using fetch / axios....... use response.status==200
if(!response) { //if you are using fetch / axios .... use response.status!=200
while(i<retry){
setTimeout(async()=>{
retry--
return await callExternalAPI(retry,interval)
},interval)
i++
}
if(i>retry) console.log("Data Not Available From This Api")
}
})
})
}
callExternalAPI(3, 1000).then((rsp) => {
console.log(rsp);
}).catch((error) => {
throw error;
})
i=0
函数调用ExternalAPI(重试,间隔){
返回新承诺((解决、拒绝)=>{
返回myapiCall()。然后((响应)=>{
if(response)返回response//if您正在使用fetch/axios…….使用response.status==200
如果(!response){//如果您正在使用fetch/axios…请使用response.status!=200
而{
重试--
返回等待调用外部LAPI(重试,间隔)
},间隔时间)
i++
}
if(i>重试)console.log(“此Api中的数据不可用”)
}
})
})
}
调用外部LAPI(31000)。然后((rsp)=>{
控制台日志(rsp);
}).catch((错误)=>{
投掷误差;
})
在出现return setTimeOut()
时,您需要返回一个承诺…...setTimeOut()
没有提供的承诺
诀窍在于知道如何“提示”setTimeOut()
有了delay()
,您可以编写:
function callExternalAPI(retry, interval) {
return myapiCall()
.then(response => {
if(response) {
return response; // Yay!
} else {
throw new Error('response was falsy'); // Doh!
}
})
.catch((error) => { // here, catch error arising async failure of myapiCall() or from response being falsy.
if(retry <= 0) {
throw error; // when retries run out, rethrow last error
} else {
return delay(interval) // here, benefit from the promisification of setTimeout().
.then(() => callExternalAPI(retry - 1, interval));
}
});
}
函数调用外部LAPI(重试,间隔){
返回myapiCall()
。然后(响应=>{
如果(答复){
返回响应;//耶!
}否则{
抛出新错误('response was falsy');//Doh!
}
})
.catch((error)=>{//此处,由myapiCall()异步失败或响应错误引起的catch错误。
if(重试callExternalAPI(重试-1,间隔));
}
});
}
不确定,但在myapicall回调中,您使用响应作为变量名,并检查是否(!result),所以请确保两者相同。@Rajsah在S.O中被问到这是一个拼写错误。如果你是一个初学者,并且在你的帖子中有承诺,你可能会发现这几个教程非常有用:。@sven hig:谢谢你的反馈。问题是我必须调用特定于api的
function delay(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
function callExternalAPI(retry, interval) {
return myapiCall()
.then(response => {
if(response) {
return response; // Yay!
} else {
throw new Error('response was falsy'); // Doh!
}
})
.catch((error) => { // here, catch error arising async failure of myapiCall() or from response being falsy.
if(retry <= 0) {
throw error; // when retries run out, rethrow last error
} else {
return delay(interval) // here, benefit from the promisification of setTimeout().
.then(() => callExternalAPI(retry - 1, interval));
}
});
}