Прерванный запрос с использованием AbortController в приложении React Redux прерван навсегда

#javascript #reactjs #redux

#javascript #reactjs #сокращение

Вопрос:

У меня есть служба выборки, которая отправляет запросы в API (используя Redux-thunk). Иногда я хочу отменить эти запросы (обычно пользователь нажимает на кнопку отмены).

Я использую AbortController в этой службе и вызываю метод прерывания этого контроллера в методах компонента. В первый раз запрос прерывается корректно, но когда я хочу сделать этот запрос снова, он также автоматически прерывается (даже если на вкладке Сети Chrome нет запроса, он немедленно отклоняется).

 // fetching service
const abortController = new AbortController();
const acSignal = abortController.signal;
export { abortController };

export default class FetchService {
    public static post(url: string): Promise<Response> {
        const requestOptions = {
            method: 'POST',
            body: ...
            signal: acSignal
        };
        return new Promise((resolve, reject) => {
            fetch(url, requestOptions)
                .then(resolve, reject);
        });
    }
}


// Component
import React from 'react';
import { abortController } from '../FetchService';
class Comp extends React.Component<{}, {}> {
   ...
   onCancelRequest = () => {
      // on cancel button click, abort request
      abortController.abort();
   }

   onButtonClick = () => {
      // initiate request
   }
}
  

onButtonClick -> запрос -> onCancelRequest -> запрос прерван -> снова onButtonClick -> запрос прерван автоматически (другого запроса onCancel нет)

Любые советы, что может быть не так? Я просто хочу снова выполнить запрос после того, как он был прерван.

Комментарии:

1. Я бы переключился на использование Axios и сохранил токен отмены, чтобы вы могли отменить их, если будет выполнено определенное действие. Функция выборки не позволяет отменять запросы «из коробки».

Ответ №1:

У меня была точно такая же проблема, и я решил ее, назначая новую AbortController при каждом fetch выполнении. Поскольку я имел дело с fetch запросами в redux thunks, я не совсем уверен в точном решении в вашем случае. Но в контексте предоставленного фрагмента это может выглядеть следующим образом:

 // fetching service
let abortController;
export { abortController };

export default class FetchService {
    public static post(url: string): Promise<Response> {
        abortController = new AbortController();
        const requestOptions = {
            method: 'POST',
            body: ...
            signal: abortController.signal
        };
        return new Promise((resolve, reject) => {
            fetch(url, requestOptions)
                .then(resolve, reject);
        });
    }
}
  

Однако, хотя это и выполняет свою работу, я не уверен, влечет ли этот подход за собой какие-либо побочные эффекты, такие как утечка памяти или зависающие контроллеры прерывания, и был бы очень признателен за информацию от более опытных разработчиков. Например, есть ли способ сбросить существующий контроллер вместо создания экземпляра и назначения нового?