Не удается выполнить новый запрос на выборку после прерывания предыдущего

#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() вызовом.