Как избежать отправки нескольких повторяющихся запросов AJAX в axios - PullRequest
3 голосов
/ 26 апреля 2019

Можно ли автоматически регулировать все запросы, поступающие в определенный список конечных точек, с помощью axios?Возможно, используя перехватчик axios?

В настоящее время я ограничиваю действие пользователя, которое отправляет запрос axios, но проблема заключается в том, что я должен писать это везде, где у меня есть действие пользователя, которое приводит к некоторому запросу AJAX.Как это

  const throttledDismissNotification = throttle(dismissNotification, 1000)

  const dismiss = (event: any) => {
    throttledDismissNotification();
  };

  render() {
    return (
      <Button onClick={dismiss}>Dismiss Notification</Button>
    )
  }

Это приводит к большому беспорядку, и мне было интересно, можно ли это автоматизировать.

Что-то вроде:

if(request.url in listOfEndpointsToThrottle && request.params in cacheOfPreviousRequestsToThisEndpoint) {
  StopRequest();
}

Очевидно, это псевдокодно вы поняли.

Ответы [ 3 ]

4 голосов
/ 26 апреля 2019

Возможно, вы могли бы попытаться использовать функцию Cancellation , которую предоставляет axios.

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

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

    import axios, { CancelToken } from 'axios';

    const pendingRequests = {};

    const makeCancellable = (headers, requestId) => {
      if (!requestId) {
        return headers;
      }

      if (pendingRequests[requestId]) {
        // cancel an existing request
        pendingRequests[requestId].cancel();
      }
      const source = CancelToken.source();
      const newHeaders = {
        ...headers,
        cancelToken: source.token
      };
      pendingRequests[requestId] = source;
      return newHeaders;
    };

    const request = ({
      url,
      method = 'GET',
      headers,
      id
    }) => {
      const requestConfig = {
        url,
        method,
        headers: makeCancellable(headers || {}, id)
      };

      return axios.request(requestConfig)
        .then((res) => {
          delete pendingRequests[id];
          return ({ data: res.data });
        })
        .catch((error) => {
          delete pendingRequests[id];
          if (axios.isCancel(error)) {
             console.log(`A request to url ${url} was cancelled`); // cancelled
          } else {
             return handleReject(error);
          }
        });
    };

    export default request;
2 голосов
/ 04 мая 2019

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

Я не вижу идеального решения этой проблемы. Но потом я прихожу к решению, которое вроде как обмануть:

Что если мы не удушим вызов axios, вместо этого мы удушим реальный запрос XMLHttpRequest?

Это значительно облегчает задачу, поскольку позволяет избежать проблем с обещаниями и проще в реализации. Идея состоит в том, чтобы реализовать кэш для недавнего запроса, и если новый запрос совпадает с последним, вы просто извлекаете результат из кэша и пропускаете запрос XMLHttpRequest.

Так как работает как Axios-перехватчики , для условного пропуска определенного вызова XHR можно использовать следующую конструкцию:

// This should be the *last* request interceptor to add
axios.interceptors.request.use(function (config) {
  /* check the cache, if hit, then intentionally throw
   * this will cause the XHR call to be skipped
   * but the error is still handled by response interceptor
   * we can then recover from error to the cached response
   **/ 
  if (requestCache.isCached(config)) {
    const skipXHRError = new Error('skip')
    skipXHRError.isSkipXHR = true
    skipXHRError.request = config
    throw skipXHRError
  } else {
    /* if not cached yet
     * check if request should be throttled
     * then open up the cache to wait for a response
     **/
    if (requestCache.shouldThrottle(config)) {
      requestCache.waitForResponse(config)
    }
    return config;
  }
});

// This should be the *first* response interceptor to add
axios.interceptors.response.use(function (response) {
  requestCache.setCachedResponse(response.config, response)
  return response;
}, function (error) {
  /* recover from error back to normalty
   * but this time we use an cached response result
   **/
  if (error.isSkipXHR) {
    return requestCache.getCachedResponse(error.request)
  }
  return Promise.reject(error);
});
1 голос
/ 29 апреля 2019

У меня похожая проблема, хотя в моих исследованиях кажется, что нет хорошего решения.Все, что я видел, было некоторыми специальными решениями, поэтому я открыл проблему для axios, надеясь, что кто-нибудь ответит на мой вопрос https://github.com/axios/axios/issues/2118

Я также нахожу эту статью Запросы на регулирование Axios , но я не пыталсярешение, которое он предложил.

И у меня есть обсуждение, связанное с этим Моя реализация запроса axounce axios навсегда оставила обещание в состоянии ожидания, есть ли лучший способ?

...