Javascript获取API太快;在第二个HTTP(获取api)请求之前完成
我有两个HTTP请求使用Javascript中的FetchAPI。我的主要语言是Java,但我负责一个前端项目,所以我不确定是否有一个简单的解决方案。我的问题是,第一个调用(命中随机服务器)命中的外部端点与第二个外部端点不同(该端点位于Azure上),但第二个端点依赖于第一个端点。基本上,第一个端点是在Azure网站(IoT hub)上创建/填充对象/IoT设备的POST请求。因此,在设备出现在网站上之前,第二个请求实际上无法做任何事情(在本例中为补丁)。我注意到它通常需要几秒钟,比如1-5秒钟才会出现 我的Fetch API如下所示:Javascript获取API太快;在第二个HTTP(获取api)请求之前完成,javascript,azure,fetch-api,Javascript,Azure,Fetch Api,我有两个HTTP请求使用Javascript中的FetchAPI。我的主要语言是Java,但我负责一个前端项目,所以我不确定是否有一个简单的解决方案。我的问题是,第一个调用(命中随机服务器)命中的外部端点与第二个外部端点不同(该端点位于Azure上),但第二个端点依赖于第一个端点。基本上,第一个端点是在Azure网站(IoT hub)上创建/填充对象/IoT设备的POST请求。因此,在设备出现在网站上之前,第二个请求实际上无法做任何事情(在本例中为补丁)。我注意到它通常需要几秒钟,比如1-5秒钟
fetch('https://first-API-endpoint-on-random-server.com/creates-thing-on-Azure', {
method: 'POST',
headers: myHeaders,
body: JSON.stringify(data),
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
// Beginning of nested Fetch
return fetch('https://second-DIFFERENT-API-endpoint-on-azure.com/tries-to-edit-thing-on-Azure', {
method: 'PATCH',
headers: myHeaders,
body: JSON.stringify(data),
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
})
因此,基本上你在我的网站UI上点击一个按钮,它应该运行这个onClick函数,并通过第一次Fetch API调用在Azure上创建/填充对象/物联网设备,然后第二次Fetch API调用应该“修补”它或编辑JSON
第一个API调用始终有效,但问题是第二个API调用似乎总是会因404“设备未找到”错误而失败,因为我认为第一个调用完成得太快,然后第二个调用尝试修补网站上甚至不存在的东西。我的解决方案是将API调用划分/拆分为两个不同的单击事件,这解决了问题,因为当用户单击第二个按钮时,第二个Fetch API调用/补丁通常都会成功
我真的想把它们组合成一个函数,这样用户永远不会知道补丁事件/http调用。我怎样才能让第二次抓取真正起作用
我可以提供您想要的任何详细信息,请并感谢您。服务器对初始请求的
200
响应似乎表明请求已正确处理,但并不表明资源已在Azure上创建。在服务器响应之后的一段时间内,会在Azure上创建资源,但客户端的第二个请求是在创建资源之前的一段时间发出的。以下是一系列可能的请求和响应的时间线:
200
,指示请求已被处理。此时,Azure已收到请求,并且可能已开始创建资源200
响应,并继续发出第二个(补丁)请求。此时,Azure可能正在创建资源,但尚未完成创建,因此它返回404
200
响应客户端。如果不可能,则可以在客户端单独或组合采取两种行动:
- 在收到第一个请求的
后,在发出第二个请求之前等待一段固定的时间。由于后端没有关于资源创建时间的指示,因此我们可以选择任意时间。下面是我们等待1秒的示例:200
函数createResource(数据){
返回获取('https://first-API-endpoint-on-random-server.com/creates-thing-on-Azure', {
方法:“POST”,
标题:myHeaders,
正文:JSON.stringify(数据),
})
}
函数updateResource(数据){
返回获取('https://second-DIFFERENT-API-endpoint-on-azure.com/tries-to-edit-thing-on-Azure', {
方法:'补丁',
标题:myHeaders,
正文:JSON.stringify(数据),
})
}
函数createAndUpdateResource(数据){
返回新承诺((解决、拒绝)=>{
返回createResource(数据)
.then(res=>res.json())
.捕获(拒绝)
.然后(resourceData=>{
设置超时(()=>{
//我们是否向修补程序请求传递数据或resourceData数据?
updateResource(资源数据)
.then(res=>res.json())
.然后(解决)
.捕获(拒绝)
});
}, 1000);
});
});
}
createAndUpdateResource({name:“abc”})
。然后(res=>{
console.log(“成功:”,res);
})
.catch(错误=>{
日志(“错误:”,错误消息);
});
- 对第二个请求使用重试机制。得到404后,我们可以对同一请求进行有限次数的重试。这可以与上面描述的超时方法相结合。下面是一个重试的示例实现:
具有重试功能(apiCall、retryCount、timeoutMS、statusForRetry){
返回新承诺((解决、拒绝)=>{
设置超时(()=>{
apiCall()
。然后(res=>{
如果(!res.ok){
如果(res.status==statusForRetry&&retryCount>0){
返回并重试(
总之,
retryCount-1,
暂停,
重试状态
);
}
拒绝(新错误(“无法更新”);
}
返回res.json();
})
.然后(解决)
.捕获(拒绝);
},超时);
});
}
函数createAndUpdateResource2(数据){
返回新承诺((解决、拒绝)=>{
返回createResource(数据)
.then(res=>res.json())
.然后(resourceData=>
用重试(
()=>更新资源(resourceData),
3,//3次重试
1000,//等待1秒
404//在404上重试
)
)
.然后(解决)
.捕获(拒绝);
});
}
第二次提取仅在第一次提取完成后运行,因为您