В общем, я пытаюсь понять, что не так с моим кодом, связанным с отменой запроса на публикацию axios. У меня есть форма, через которую пользователь может сделать запрос на поиск фильмов в openai. Пока поиск продолжается, я предоставляю пользователю кнопку отмены, позволяющую прервать поиск и ввести новый поисковый запрос. Если во время тестирования я прерву запрос, я все равно получу данные, и они все равно будут обрабатываться, как если бы запрос не был отменен.
Это происходит в компоненте React, который я посвятил обработке запроса openai. Согласно моему package.json, я использую Axios 9.5.0. Первое, что я делаю внутри компонента, — устанавливаю состояние, а затем:
const controller = new AbortController();
Вот обработчик, когда пользователь отправляет поиск:
const handleSubmit = async () => {
(set some states to set up correct user interface)
try {
const searchResults = await axios.post(
"/api/movies/ai-search",
{
userRequest: request,
},
{ signal: controller.signal }
);
const jsonResults = JSON.parse(searchResults.data);
(do stuff with the returned data)
} catch (err) {
if (axios.isCancel(err)) {
console.info("Request cancelled");
} else {
console.info(err);
}
(set some more states to reflect error message)
);
}
};
А вот обработчик, когда пользователь нажимает кнопку, чтобы отменить текущий поиск:
const handleSearchCancel = (e: React.MouseEvent<HTMLButtonElement>) => {
// handler for when user cancels search
console.info("Cancelling the search") // confirm I made it to the handler
controller.abort();
(set a couple of states to update the UI)
};
Одна из проблем, которая, как мне показалось, может заключаться в том, что все настройки состояния: большинство из них создаются из родительского компонента. Может ли это быть причиной проблемы? В любом случае, если я отправлю поиск, а затем отменю его, я получу журнал консоли о том, что нахожусь в правильном обработчике. Но если я подожду еще несколько минут, результаты поиска появятся и будут обработаны так, как будто запрос не был отменен.
Обновлено:
По предложению Дата я переключился на настройку useRef:
const abortControllerRef = useRef<AbortController>(new AbortController());
Это сработало для первого поиска... но все последующие поиски немедленно отменяются без участия пользователя. При исследовании этого вопроса мне кажется, что мне нужно создать новый AbortController для каждого запроса. НО, поскольку я использую useRef, я не могу сделать это в обработчике кликов. Попробую сделать это в кастомном хуке.





Можете ли вы еще раз проверить версию вашего Axios? Axios 9.5.0 не существует.
Гость, вы «(установите несколько состояний для настройки правильного пользовательского интерфейса)» сделали контроллер в запросе и в handleCancel разными. Так что можешь попробовать const abortControllerRef = useRef<AbortController>(new AbortController()); или const abortControllerRef = useMemo(()=> {return new AbortController()},[])
Дат, чтобы убедиться, что я правильно понимаю, useRef сохраняет свое значение, если измененное состояние приводит к повторному рендерингу, поэтому, помещая новый AbortController в ссылку, он не инициализируется повторно. Я правильно это понимаю?
Правильно, основная цель — сохранить одинаковые оба контроллера.
Отчасти это сработало! Когда я отменяю запрос (abortControllerRef.current.abort();), он отменяется, я получаю соответствующую запись в журнале «запрос отменен». НО... если я отправлю еще один поиск, он будет немедленно отменен без вмешательства пользователя.
И по поводу вашего замешательства по поводу версии аксиоса. Команда npm -v axis возвращает версию npm. Вы можете попробовать другое имя пакета, оно всегда возвращает 9.5.0. Поэтому, если вы хотите проверить версию пакета, вам следует использовать sudo npm view axios version или npm view axios version.
Да, это верно. Потому что атрибут aborted теперь верен. Вы можете увидеть изображение, которое я добавил в свой ответ, взятое из пакета axios. Таким образом, он может решить проблему, объявив, что ссылка равна нулю. После этого, когда вы отправили запрос, сделайте так, чтобы он стал abortControllerRef = useRef<AbortController>(new AbortController());. Наконец, когда вы отмените запрос, сделайте его снова равным нулю.
Давайте продолжим обсуждение в чате.
Хорошо, с помощью Дата мы это выяснили.
const abortRef = useRef<AbortController>(new AbortController())
и я мог бы сослаться на него в функции cancelSearchHandler. НО... как только я это сделал, поиск НАВСЕГДА прерывается. Все последующие поиски без обновления были автоматически отменены. Так...
Повторно создайте новый экземпляр AbortController при отправке поиска. ЗА ИСКЛЮЧЕНИЕМ я не смог сделать это внутри обработчика отправки. Невозможно использовать хуки React внутри обработчиков, они должны находиться на верхнем уровне компонента. Итак, «мы» наконец получили ответ...
Забудьте о хуках React, используйте стандартный JavaScript для создания экземпляра контроллера, но делайте это ВНЕ компонента (гениально, Дат!). Тот же модуль, только за пределами компонента. Так:
let controller: AbortController;
Это было вне компонента, что делало его одинаково доступным как для обработчика отправки, так и для обработчика отмены. Затем используйте его как обычно.
Да, меня это тоже смутило. В моем package.json есть
axios: "^1.6.7", но когда я делаюnpm -v axisв командной строке, я получаю обратно 9.5.0.