Javascript 获取 API 太快;在第二个 HTTP(获取 api)请求之前完成
Javascript Fetch API too fast; finishes before second HTTP (fetch api) request
我有 2 个 HTTP 请求使用 Java 脚本中的 Fetch API。我的主要语言是 Java 但我负责一个前端项目,所以我不确定是否有一个简单的解决方案。我的问题是第一个调用(命中随机服务器)命中的外部端点不同于第二个外部端点(此端点在 Azure 上),但第二个端点依赖于第一个端点。基本上,第一个端点是 POST 请求 creates/populates Azure 网站(IoT 中心)上的 object/IoT 设备。因此,在设备出现在网站上之前,第二个请求实际上无法执行任何操作(在本例中为 PATCH)。我注意到它通常需要几秒钟,比如 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 函数和 create/populate Azure 上的 object/IoT 设备通过第一次获取API 调用,然后第二个 Fetch API 调用应该 "PATCH" 它或编辑 JSON.
第一个 API 调用 总是 有效 但问题是第二个 API 调用似乎总是因 404 "device not found" 错误,因为我认为第一个调用完成得太快,然后第二个调用试图修补网站上什至不存在的东西。我的解决方案是将 out/split 和 API 调用划分为两个不同的点击事件,这解决了用户点击第二个按钮时的问题,即 2nd Fetch API call/PATCH 通常总是成功。
我真的很想将它们组合成一个函数,这样用户就永远不会知道 PATCH event/http 调用。我怎样才能让这第二个 Fetch 真正起作用?
我可以提供您想要的任何详细信息,谢谢
看起来服务器对初始请求的 200
响应表明请求已正确处理,但并未表明资源已在 Azure 上创建。资源是在服务器响应后的一段时间内在 Azure 上创建的,但是客户端的第二个请求是在资源创建之前 的某个时间发出的。以下是可能的请求和响应序列的时间表:
- 客户端(Web 浏览器)向服务器发出第一个 (POST) 请求。
- 服务器收到请求,向Azure发出创建资源的请求,returns一个
200
表示请求已经处理。此时,Azure 已收到请求并可能开始创建资源。
- 客户端(Web 浏览器)收到来自服务器的
200
响应并继续发出第二个 (PATCH) 请求。此时,Azure 可能正在创建资源,但尚未完成创建,因此它 returns a 404
.
这个问题可以在后端解决,例如让服务器等待在 Azure 上创建资源,然后再用 200
响应客户端。如果那不可能,可以在客户端单独或组合采取两条措施:
- 在收到第一个请求
200
后,等待一段固定的时间再发出第二个请求。由于我们没有来自后端的关于何时创建资源的指示,我们可以选择任意时间。这是我们等待 1 秒的示例:
function createResource(data) {
return fetch('https://first-API-endpoint-on-random-server.com/creates-thing-on-Azure', {
method: 'POST',
headers: myHeaders,
body: JSON.stringify(data),
})
}
function updateResource(data) {
return fetch('https://second-DIFFERENT-API-endpoint-on-azure.com/tries-to-edit-thing-on-Azure', {
method: 'PATCH',
headers: myHeaders,
body: JSON.stringify(data),
})
}
function createAndUpdateResource(data) {
return new Promise((resolve, reject) => {
return createResource(data)
.then(res => res.json())
.catch(reject)
.then(resourceData => {
setTimeout(() => {
// do we pass data or resourceData data to the PATCH request?
updateResource(resourceData)
.then(res => res.json())
.then(resolve)
.catch(reject)
});
}, 1000);
});
});
}
createAndUpdateResource({ name: "abc" })
.then(res => {
console.log("success:", res);
})
.catch(err => {
console.log("error: ", err.message);
});
- 对第二个请求使用重试机制。在获得 404 时,我们可以对同一请求进行有限次数的重试。这可以与上述超时方法结合使用。这是重试的示例实现:
function withRetry(apiCall, retryCount, timeoutMS, statusForRetry) {
return new Promise((resolve, reject) => {
setTimeout(() => {
apiCall()
.then(res => {
if (!res.ok) {
if (res.status === statusForRetry && retryCount > 0) {
return withRetry(
apiCall,
retryCount - 1,
timeoutMS,
statusForRetry
);
}
reject(new Error("couldn't update"));
}
return res.json();
})
.then(resolve)
.catch(reject);
}, timeoutMS);
});
}
function createAndUpdateResource2(data) {
return new Promise((resolve, reject) => {
return createResource(data)
.then(res => res.json())
.then(resourceData =>
withRetry(
() => updateResource(resourceData),
3, // 3 retries
1000, // wait 1 second
404 // retry on 404
)
)
.then(resolve)
.catch(reject);
});
}
我有 2 个 HTTP 请求使用 Java 脚本中的 Fetch API。我的主要语言是 Java 但我负责一个前端项目,所以我不确定是否有一个简单的解决方案。我的问题是第一个调用(命中随机服务器)命中的外部端点不同于第二个外部端点(此端点在 Azure 上),但第二个端点依赖于第一个端点。基本上,第一个端点是 POST 请求 creates/populates Azure 网站(IoT 中心)上的 object/IoT 设备。因此,在设备出现在网站上之前,第二个请求实际上无法执行任何操作(在本例中为 PATCH)。我注意到它通常需要几秒钟,比如 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 函数和 create/populate Azure 上的 object/IoT 设备通过第一次获取API 调用,然后第二个 Fetch API 调用应该 "PATCH" 它或编辑 JSON.
第一个 API 调用 总是 有效 但问题是第二个 API 调用似乎总是因 404 "device not found" 错误,因为我认为第一个调用完成得太快,然后第二个调用试图修补网站上什至不存在的东西。我的解决方案是将 out/split 和 API 调用划分为两个不同的点击事件,这解决了用户点击第二个按钮时的问题,即 2nd Fetch API call/PATCH 通常总是成功。
我真的很想将它们组合成一个函数,这样用户就永远不会知道 PATCH event/http 调用。我怎样才能让这第二个 Fetch 真正起作用?
我可以提供您想要的任何详细信息,谢谢
看起来服务器对初始请求的 200
响应表明请求已正确处理,但并未表明资源已在 Azure 上创建。资源是在服务器响应后的一段时间内在 Azure 上创建的,但是客户端的第二个请求是在资源创建之前 的某个时间发出的。以下是可能的请求和响应序列的时间表:
- 客户端(Web 浏览器)向服务器发出第一个 (POST) 请求。
- 服务器收到请求,向Azure发出创建资源的请求,returns一个
200
表示请求已经处理。此时,Azure 已收到请求并可能开始创建资源。 - 客户端(Web 浏览器)收到来自服务器的
200
响应并继续发出第二个 (PATCH) 请求。此时,Azure 可能正在创建资源,但尚未完成创建,因此它 returns a404
.
这个问题可以在后端解决,例如让服务器等待在 Azure 上创建资源,然后再用 200
响应客户端。如果那不可能,可以在客户端单独或组合采取两条措施:
- 在收到第一个请求
200
后,等待一段固定的时间再发出第二个请求。由于我们没有来自后端的关于何时创建资源的指示,我们可以选择任意时间。这是我们等待 1 秒的示例:
function createResource(data) {
return fetch('https://first-API-endpoint-on-random-server.com/creates-thing-on-Azure', {
method: 'POST',
headers: myHeaders,
body: JSON.stringify(data),
})
}
function updateResource(data) {
return fetch('https://second-DIFFERENT-API-endpoint-on-azure.com/tries-to-edit-thing-on-Azure', {
method: 'PATCH',
headers: myHeaders,
body: JSON.stringify(data),
})
}
function createAndUpdateResource(data) {
return new Promise((resolve, reject) => {
return createResource(data)
.then(res => res.json())
.catch(reject)
.then(resourceData => {
setTimeout(() => {
// do we pass data or resourceData data to the PATCH request?
updateResource(resourceData)
.then(res => res.json())
.then(resolve)
.catch(reject)
});
}, 1000);
});
});
}
createAndUpdateResource({ name: "abc" })
.then(res => {
console.log("success:", res);
})
.catch(err => {
console.log("error: ", err.message);
});
- 对第二个请求使用重试机制。在获得 404 时,我们可以对同一请求进行有限次数的重试。这可以与上述超时方法结合使用。这是重试的示例实现:
function withRetry(apiCall, retryCount, timeoutMS, statusForRetry) {
return new Promise((resolve, reject) => {
setTimeout(() => {
apiCall()
.then(res => {
if (!res.ok) {
if (res.status === statusForRetry && retryCount > 0) {
return withRetry(
apiCall,
retryCount - 1,
timeoutMS,
statusForRetry
);
}
reject(new Error("couldn't update"));
}
return res.json();
})
.then(resolve)
.catch(reject);
}, timeoutMS);
});
}
function createAndUpdateResource2(data) {
return new Promise((resolve, reject) => {
return createResource(data)
.then(res => res.json())
.then(resourceData =>
withRetry(
() => updateResource(resourceData),
3, // 3 retries
1000, // wait 1 second
404 // retry on 404
)
)
.then(resolve)
.catch(reject);
});
}