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

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

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

【问题讨论】:

    标签: reactjs redux react-router axios


    【解决方案1】:

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

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

    【讨论】:

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

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

    处理这个问题的其他方法是,(我不确定axios 但是)XMLHttpRequest 有abort 方法。您可以在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;
      

      【讨论】:

        猜你喜欢
        • 2017-10-14
        • 2018-12-02
        • 1970-01-01
        • 1970-01-01
        • 2020-10-28
        • 2019-03-07
        • 2019-10-20
        • 2021-07-02
        • 2019-04-24
        相关资源
        最近更新 更多