我有一个问题,我可以肯定我不是唯一一个遇到问题的人。尽管我试图找到解决方案,但我并没有真正找到适合我目的的东西。
我不会发布太多代码,因为它不是真正的代码问题,而是更多的逻辑问题。
想象一下,我有以下钩子:
useEffect(() => {
fetchFromApi(props.match.params.id);
}, [props.match.params.id]);
想象一下fetchFromApi的结果显示在UI的一个简单表中。
现在,可以说用户单击导航中的一个实体,因此浏览器URL中的ID属性更改,并且效果触发,从而导致API调用。假设具有此特定ID的呼叫需要5秒钟。
在这5秒钟内,用户再次单击导航中的元素,因此该挂钩再次触发。这次,API调用仅需0.1秒。结果立即显示。
但是第一个电话仍在运行。完成后,它将覆盖当前结果,从而导致在错误的导航部分中显示错误的数据。
有没有简单的方法可以解决此问题?我知道我默认情况下无法取消承诺,但是我也知道有一些方法可以实现它...
此外,fetchFromApi可能不是单个API调用,而是对多个端点的多次调用,因此整个过程可能会变得非常棘手...
感谢您的帮助。
答案 0 :(得分:0)
此问题的解决方案非常简单,您只需确定所获得的响应是否来自最新的API调用,然后才能确定。您可以通过将triggerTime存储在ref中来实现。如果再次调用了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。