React - Old promise覆盖新结果

问题描述 投票:1回答:1

我有一个问题,我很确定我不是唯一一个有过这个问题的人......虽然我试图找到一个解决方案,但我找不到符合我目的的东西。

我不会发布很多代码,因为它不是真正的代码问题,而是更多的逻辑问题。

想象一下,我有以下钩子:

useEffect(() => {
    fetchFromApi(props.match.params.id);
}, [props.match.params.id]);

想象一下,fetchFromApi的结果显示在UI中的一个简单表中。

现在假设用户点击导航中的实体,因此浏览器URL中的ID prop会发生变化并触发效果,从而导致API调用。假设使用此特定ID的呼叫需要5秒钟。

在这5秒钟内,用户再次点击导航中的元素,因此钩子再次触发。这次,API调用只需要0.1秒。结果立即显示出来。

但第一次通话仍在运行。完成后,它会覆盖当前结果,导致错误导航部分显示错误数据。

有没有简单的方法来解决这个问题?我知道默认情况下我不能取消承诺,但我也知道有办法实现它...

此外,fetchFromApi可能不是单个API调用,而是多个调用多个端点,因此整个事情可能变得非常棘手......

谢谢你的帮助。

reactjs promise es6-promise
1个回答
0
投票

对此的解决方案非常简单,您只需要确定您获得的响应是​​否来自最新的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。

© www.soinside.com 2019 - 2024. All rights reserved.