我有一个问题,我很确定我不是唯一一个有过这个问题的人......虽然我试图找到一个解决方案,但我找不到符合我目的的东西。
我不会发布很多代码,因为它不是真正的代码问题,而是更多的逻辑问题。
想象一下,我有以下钩子:
useEffect(() => {
fetchFromApi(props.match.params.id);
}, [props.match.params.id]);
想象一下,fetchFromApi的结果显示在UI中的一个简单表中。
现在假设用户点击导航中的实体,因此浏览器URL中的ID prop会发生变化并触发效果,从而导致API调用。假设使用此特定ID的呼叫需要5秒钟。
在这5秒钟内,用户再次点击导航中的元素,因此钩子再次触发。这次,API调用只需要0.1秒。结果立即显示出来。
但第一次通话仍在运行。完成后,它会覆盖当前结果,导致错误导航部分显示错误数据。
有没有简单的方法来解决这个问题?我知道默认情况下我不能取消承诺,但我也知道有办法实现它...
此外,fetchFromApi可能不是单个API调用,而是多个调用多个端点,因此整个事情可能变得非常棘手......
谢谢你的帮助。
对此的解决方案非常简单,您只需要确定您获得的响应是否来自最新的API调用,然后才能确定。你可以通过在ref中存储triggerTime来实现。如果API调用已被触发另一次,则ref将存储不同的值,但是闭包变量将保持相同的先前设置值,这意味着在此之后已触发另一个API调用,因此我们不需要接受目前的结果。
const timer = useRef(null);
useEffect(() => {
fetchFromApi(props.match.params.id, timer);
}, [props.match.params.id]);
function fetchFromApi(id, timer) {
timer.current = Date.now();
const triggerTime = timer.current;
fetch('path').then(() => {
if(timer.current == triggerTime) {
// process result here
// accept response and update state
}
})
}
处理此类方案的其他方法是取消先前挂起的API请求。如果你使用Axios
它会为你提供你可以使用的cancelToken,同样你也可以取消XMLHttpRequests。