Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 我如何防止比赛中出现比赛状态?_Javascript_Reactjs_Promise_Race Condition - Fatal编程技术网

Javascript 我如何防止比赛中出现比赛状态?

Javascript 我如何防止比赛中出现比赛状态?,javascript,reactjs,promise,race-condition,Javascript,Reactjs,Promise,Race Condition,我为React编写了一个方便的钩子,它跟踪承诺是否正在运行、是否存在错误以及结果是什么。它是这样使用的: const MyComponent = (props: IProps) => { const [promise, setPromise} = useState<Promise | undefined>(); const { hasRun, isWaiting, results, error } = useService(promi

我为React编写了一个方便的钩子,它跟踪承诺是否正在运行、是否存在错误以及结果是什么。它是这样使用的:

const MyComponent = (props: IProps) => {
  const [promise, setPromise} = useState<Promise | undefined>();
  const {
    hasRun,
    isWaiting,
    results,
    error
  } = useService(promise);

  const doSomething = () => {
    setPromise(runSomeAsyncCode());
  };

  return (
    <div>...</div>
  );
};
constmycomponent=(props:IProps)=>{
const[promise,setPromise}=useState();
常数{
哈斯伦,
我在等待,
后果
错误
}=使用服务(承诺);
常数doSomething=()=>{
setPromise(runSomeAsyncCode());
};
返回(
...
);
};
它只不过是随着承诺的启动、运行、成功或失败而更新的一组状态:

export const useService = <T>(promise?: Promise<T>) => {
    const [hasRun, setHasRun] = useState<boolean>(false);
    const [isWaiting, setIsWaiting] = useState<boolean>(false);
    const [error, setError] = useState<Error | undefined>(undefined);
    const [results, setResults] = useState<T | undefined>();

    useEffect(() => {
        if (!promise) {
            return;
        }

        (async () => {
            if (!hasRun) {
                setHasRun(true);
            }
            setError(undefined);

            setIsWaiting(true);
            try {
                const r = await promise;
                setResults(r);
            } catch (err) {
                setResults(undefined);
                setError(err);
            } finally {
                setIsWaiting(false);
            }
        })();
    }, [promise]);

    return {
        error,
        hasRun,
        isWaiting,
        results,
    };
};
export const useService=(承诺?:承诺)=>{
const[hasRun,setHasRun]=useState(false);
const[isWaiting,setIsWaiting]=useState(false);
const[error,setError]=useState(未定义);
const[results,setResults]=useState();
useffect(()=>{
如果(!承诺){
回来
}
(异步()=>{
如果(!hasRun){
setHasRun(真);
}
设置错误(未定义);
setIsWaiting(true);
试一试{
const r=等待承诺;
setResults(r);
}捕捉(错误){
setResults(未定义);
设置错误(err);
}最后{
setIsWaiting(假);
}
})();
},[承诺];
返回{
错误
哈斯伦,
我在等待,
后果
};
};
我的问题是,如果承诺在前一个承诺解决之前更新,那么前一个承诺的结果或错误仍将返回到组件。例如,启动两个AJAX请求,其中第一个在一分钟后失败,而第二个在几秒钟内解决,这会导致最初的成功,但随后会报告失败几分钟后

如何修改钩子,使其不会在承诺更改的同时调用setState以获得错误或成功


Codepen:

为什么不跟踪当前的
承诺
,并在承诺发生变化时解除其效力

export const useService=(承诺?:承诺)=>{
const[hasRun,setHasRun]=useState(false);
const[isWaiting,setIsWaiting]=useState(false);
const[error,setError]=useState(未定义);
const[results,setResults]=useState();
const promiseRef=useRef(promise);
promiseRef.current=promise;//**始终保持引用最新
useffect(()=>{
如果(!承诺){
回来
}
(异步()=>{
setHasRun(真);
设置错误(未定义);
setIsWaiting(true);
试一试{
const r=等待承诺;
if(promiseRef.current!==承诺){
回来
}
setResults(r);
setIsWaiting(假);
}捕捉(错误){
if(promiseRef.current!==承诺){
回来
}
setResults(未定义);
设置错误(err);
setIsWaiting(假);
}
})();
//您可能希望在承诺更改时重置状态
return()=>{
setHasRun(假);
setIsWaiting(假);
设置错误(未定义);
setResults(未定义);
}
},[承诺];
返回{
错误
哈斯伦,
我在等待,
后果
};
};
正如前面所指出的,
useRef
不仅仅适用于DOM元素引用

本质上,useRef就像一个“盒子”,可以在其.current属性中保存可变值。[…]改变.current属性不会导致重新呈现


我在这里使用
useRef
的原因是因为我们需要一个可变值,它可以保存最新的
promise
参数,而不会导致重新加载。因为
promiseRef
从不更改(只有
。current
会更改),您可以使用
**
在行上指定最新的值,并在异步函数中访问它,即使时间已经过去,组件已经重新加载。

useRef钩子做什么?我以为refs是用于访问DOM节点的。如果它只是用于跟踪单个值,为什么状态不起作用?编辑以回答我为什么使用
useRef
over
useState