Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/42.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 无法通过最大重试次数解决承诺问题_Javascript_Node.js_Promise_Es6 Promise - Fatal编程技术网

Javascript 无法通过最大重试次数解决承诺问题

Javascript 无法通过最大重试次数解决承诺问题,javascript,node.js,promise,es6-promise,Javascript,Node.js,Promise,Es6 Promise,在过去的几天里,我一直在与Promise和一个初学者斗争。我必须调用一个外部API并检查是否有响应。如果为null,则再次调用api并进行最大重试尝试,这是可配置的。我尝试了以下方法,但不确定我缺少了什么。这是我做的一个例子 如果数据可用,则显示数据可用。如果不是,则重试一段时间,如果达到零,则使用API中不可用的数据进行解析。如果数据在重试后可用(例如:第二次),则停止并显示响应 function callExternalAPI(retry, interval) { try { re

在过去的几天里,我一直在与Promise和一个初学者斗争。我必须调用一个外部API并检查是否有响应。如果为null,则再次调用api并进行最大重试尝试,这是可配置的。我尝试了以下方法,但不确定我缺少了什么。这是我做的一个例子

如果数据可用,则显示数据可用。如果不是,则重试一段时间,如果达到零,则使用API中不可用的数据进行解析。如果数据在重试后可用(例如:第二次),则停止并显示响应

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));
        }
    });
}