取消路线更改请求(React / Redux / Axios)

时间:2017-07-07 13:40:55

标签: reactjs redux react-router axios

是否有方便的方法可以使用<script src="https://code.jquery.com/jquery-2.2.3.min.js" integrity="sha256-a23g1Nt4dtEYOj7bR+vTu7+T8VP13humZFBJNIYoEJo=" crossorigin="anonymous"></script> <div class="appendme">The div that should be appended</div> <button class="appendbtn" type="button">Click to append</button>axiosredux-thunk取消所有路线更改的发送请求?我知道redux有取消令牌,应该添加到每个请求中,我可以调用axios取消它。

P.S。目前我在source.cancel(/* message */)处理此问题。也许有更好的东西?

3 个答案:

答案 0 :(得分:0)

我找到的最简单的方法是将source存储在状态中,如果请求正在发送,则使用source.cancel

componentWillUnmount() { if(isLoading) { source.cancel() } }

答案 1 :(得分:0)

非常简单的解决方案是声明isMounted变量,然后在组件卸载时将其设置为false

其他解决此问题的方法是,(我不确定axios,但XMLHttpRequest上有abort方法。您可以在xhr.abort()上致电componentWillUnmount。 在这里检查:https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/abort

最后还有一个行业解决方案:)来自Netflix UI工程师。他们已经为RxJS编写了Redux中间件,并使用RxJS运算符来启动和取消请求。

该库称为redux-observable。我建议看一下示例:https://redux-observable.js.org/docs/recipes/Cancellation.html

您可以在此处观看有关此话题的讨论:https://youtu.be/AslncyG8whg

答案 2 :(得分:0)

我找到了一个简单的解决方案(没有 redux)来做到这一点。您所需要的只是 axios 请求中的 cancelToken。之后,使用 useHook检测路由变化。然后,在路由卸载时使用 TOKEN 取消请求并生成新的 TOKEN 以进行新的请求。有关更多详细信息,请参阅 Axios 文档 (https://github.com/axios/axios)。

Route.tsx 文件

import React, { useEffect } from 'react';
import { Route, RouteProps, useLocation } from 'react-router-dom';
import API from 'src/services/service';

const CustomRoute = (props: RouteProps) => {
  const location = useLocation();

  // Detect Route Change
  useEffect(() => {
    handleRouteChange();

    return () => {
      handleRouteComponentUnmount();
    };
  }, [location?.pathname]);

  function handleRouteChange() {
    // ...
  }

  function handleRouteComponentUnmount() {
    API.finishPendingRequests('RouteChange');
  }

  return <Route {...props} />;
};

export default CustomRoute;

Service.ts 文件

import { Response } from 'src/models/request';
import axios, {AxiosInstance, AxiosResponse } from 'axios';

const ORIGIN_URL = 'https://myserver.com'
const BASE_URL = ORIGIN_URL + '/api';
let CANCEL_TOKEN_SOURCE = axios.CancelToken.source();
    
function generateNewCancelTokenSource() {
  CANCEL_TOKEN_SOURCE = axios.CancelToken.source();
}

export const axiosInstance: AxiosInstance = axios.create({
  baseURL: BASE_URL,
});

const API = {
  get<DataResponseType = any>(
    endpoint: string,
  ): Promise<AxiosResponse<Response<DataResponseType>>> {
    return axiosInstance.get<Response<DataResponseType>>(endpoint, {
      cancelToken: CANCEL_TOKEN_SOURCE.token,
    });
  },

  // ...Another Functions

  finishPendingRequests(cancellationReason: string) {
    CANCEL_TOKEN_SOURCE.cancel(cancellationReason);
    generateNewCancelTokenSource();
  },
};

export default API;