Javascript获取API太快;在第二个HTTP(获取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秒钟

我有两个HTTP请求使用Javascript中的FetchAPI。我的主要语言是Java,但我负责一个前端项目,所以我不确定是否有一个简单的解决方案。我的问题是,第一个调用(命中随机服务器)命中的外部端点与第二个外部端点不同(该端点位于Azure上),但第二个端点依赖于第一个端点。基本上,第一个端点是在Azure网站(IoT hub)上创建/填充对象/IoT设备的POST请求。因此,在设备出现在网站上之前,第二个请求实际上无法做任何事情(在本例中为补丁)。我注意到它通常需要几秒钟,比如1-5秒钟才会出现

我的Fetch API如下所示:

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上创建资源,但客户端的第二个请求是在创建资源之前的一段时间发出的。以下是一系列可能的请求和响应的时间线:

  • 客户端(web浏览器)向服务器发出第一个(POST)请求
  • 服务器接收请求,向Azure发出创建资源的请求,并返回一个
    200
    ,指示请求已被处理。此时,Azure已收到请求,并且可能已开始创建资源
  • 客户端(web浏览器)从服务器接收
    200
    响应,并继续发出第二个(补丁)请求。此时,Azure可能正在创建资源,但尚未完成创建,因此它返回
    404
  • 这个问题可以在后端解决,例如,让服务器等待在Azure上创建资源,然后用
    200
    响应客户端。如果不可能,则可以在客户端单独或组合采取两种行动:

    • 在收到第一个请求的
      200
      后,在发出第二个请求之前等待一段固定的时间。由于后端没有关于资源创建时间的指示,因此我们可以选择任意时间。下面是我们等待1秒的示例:
    函数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上重试
    )
    )
    .然后(解决)
    .捕获(拒绝);
    });
    }
    
    第二次提取仅在第一次提取完成后运行,因为您