Реакция - Старое обещание заменяет новый результат - PullRequest
0 голосов
/ 26 февраля 2019

У меня есть проблема, и я уверен, что я не единственный, кто когда-либо имел ее ... Хотя я пытался найти решение, я действительно не нашел то, что соответствует моей цели.

Я не буду публиковать много кода, так как это не проблема кода, а проблема логики.

Представьте, что у меня есть следующий хук:

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

Представьте, что результат fetchFromApi отображается в простой таблице в пользовательском интерфейсе.

Теперь предположим, что пользователь нажимает насущность в навигации, поэтому пропадает идентификатор в URL браузера и эффект срабатывает, что приводит к вызову API.Допустим, вызов с этим конкретным идентификатором занимает 5 секунд.

В течение этих 5 секунд пользователь снова нажимает на элемент в навигации, поэтому перехват запускается снова.На этот раз вызов API занимает всего 0,1 секунды.Результат сразу отображается.

Но первый звонок все еще выполняется.После завершения он перезаписывает текущий результат, что приводит к отображению неверных данных в неправильном разделе навигации.

Есть ли простой способ решить эту проблему?Я знаю, что не могу отменить обещания по умолчанию, но я также знаю, что есть способы достичь этого ...

Также возможно, что fetchFromApi - это не один вызов API, а несколько вызововк нескольким конечным точкам, так что все может стать очень сложно ...

Спасибо за любую помощь.

1 Ответ

0 голосов
/ 27 февраля 2019

Решение этого чрезвычайно простое, вам просто нужно определить, был ли ответ, который вы получили, от последнего вызова API или нет, и только после этого, кроме него.Вы можете сделать это, сохранив triggerTime в ref.Если вызов API был инициирован в другой раз, ссылка будет хранить другое значение, однако переменная замыкания будет содержать то же самое ранее установленное значение, и это означает, что после этого был инициирован другой вызов 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, которую вы можете использовать, и аналогичным образом вы также можете отменять запросы XMLHttpRequest.

...