Я написал удобную ловушку для 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>
);
};
Это не более чем группа состояний, которые обновляются при запуске, выполнении, успешном или неудачном выполнении обещания:
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,
};
};
Моя проблема в том, что если обещание обновляется до разрешения предыдущего обещания, то результаты или ошибка предыдущего обещания все равно будут возвращены компоненту. Например, запуск пары AJAX запросов, где первый не выполняется через минуту, а второй разрешается за пару секунд, приводит к первоначальному успеху, но затем к сообщению об ошибке через минуту.
Как я могу изменить ловушку, чтобы она не вызывала setState для ошибки или успеха, если обещание за это время изменилось?
Codepen: https://codepen.io/whiterook6/pen/gOPwJGq