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

Posted

技术标签:

【中文标题】取消路由更改请求 (React/Redux/Axios)【英文标题】:Cancel requests on route change (React/Redux/Axios) 【发布时间】:2017-12-11 20:12:18 【问题描述】:

是否有方便的方法可以使用axiosredux-thunkredux 取消任何路由更改的所有发送请求?我知道axios 有取消令牌,应该添加到每个请求中,我可以调用source.cancel(/* message */) 取消它。

附:目前我在componentWillUnmount 处理这个问题。也许有更好的东西?

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

但是他们说在 store 中存储函数不是一个好主意。Store 应该是可序列化的。你可以阅读这个here。我也在寻找解决方案。【参考方案2】:

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

处理这个问题的其他方法是,(我不确定axios 但是)XMLHttpRequestabort 方法。您可以在componentWillUnmount 上致电xhr.abort()。 在这里查看: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

【讨论】:

【参考方案3】:

我找到了一个简单的解决方案(没有 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;

【讨论】:

以上是关于取消路由更改请求 (React/Redux/Axios)的主要内容,如果未能解决你的问题,请参考以下文章

反应路由器/反应查询不会取消/发出导航请求 - 反应/打字稿

路由改变后取消前一个组件的所有http请求

vue路由变化时使用axios取消所有请求

vue路由跳转取消上个页面的异步请求

使用 Sammy.js 取消路由而不影响历史

取消操作运行,当拉取请求更改时