#javascript #xmlhttprequest #fetch
#javascript #xmlhttprequest #выборка
Вопрос:
Мне нужно изменить параметры, которые определяют, какие данные должны поступать из моих запросов, также это приложение должно обновляться через регулярные промежутки времени. Если пользователь изменяет параметр в середине незавершенного запроса, все начинает вести себя странно и возникает некоторое неожиданное поведение.
Итак, мой подход состоял в том, чтобы прервать все предыдущие запросы перед запуском новых, но после использования await controller.abort()
кажется, что следующие запросы никогда не запускаются, нужно ли мне очистить сигнал или что-то в этом роде?
const controller = new AbortController();
const async fetchData = (url, body = null) => {
let data;
const signal = controller.signal;
const headers = { ... };
response = await fetch(url, body ? {
method: "POST",
body: JSON.stringify(body),
signal,
headers
} : { headers, signal });;
data = await response.json()
return data
}
const firstData = await fetchData(url1, body1);
await controller.abort();
const secondData= await fetchData(url2, body2);
Происходит то, что secondData
всегда происходит undefined
, на самом деле этот второй запрос никогда не выполняется (смотря по сетевому трафику). Если я останавливаю исходный код и пытаюсь выполнить его await fetchData(url2)
после .abort()
выполнения, он выдает ошибку, в которой говорится, что Uncaught SyntaxError: await is only valid in async function
или если я пытаюсь запустить его без await
, он возвращает ожидающее обещание, но фактический запрос нигде не отображается на вкладке traffic.
Решаемая
Применив то, что было предложено в ansewr, я создал оболочку для функции, чтобы каждый раз вызывать новые контроллеры.
let controller = null;
let fetchData = null;
const initializeFetchData = () => {
const controller = new AbortController();
const async fetchData = (url, body = null) => {
let data;
const signal = controller.signal;
const headers = { ... };
response = await fetch(url, body ? {
method: "POST",
body: JSON.stringify(body),
signal,
headers
} : { headers, signal });;
data = await response.json()
return data
}
}
initializeFetchData();
const firstData = await fetchData(url1, body1);
controller.abort();
initializeFetchData();
const secondData= await fetchData(url2, body2);
Ответ №1:
Вы используете одно и то же AbortController
для двух разных запросов. После вызова .abort()
на AbortController
вы обновили его состояние, AbortSignal
что затем делает второй запрос недействительным.
Вы должны использовать отдельный AbortController
для каждого запроса, если хотите такого поведения. Конечно, вполне допустимо повторно использовать an AbortController
для нескольких fetch
запросов, если вы хотите иметь возможность прервать их все за один раз.
Пара других моментов…
.abort()
это синхронный метод, который возвращает,void
поэтому вам не нуженawait
префикс при вызове.abort()
.- В вашем примере кода первый запрос никогда не будет прерван, поскольку вы ожидаете
fetch
запроса, который завершится перед.abort()
вызовом.