Javascript 我如何防止比赛中出现比赛状态?
我为React编写了一个方便的钩子,它跟踪承诺是否正在运行、是否存在错误以及结果是什么。它是这样使用的: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
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
overuseState
。