如何在拦截器中使用Axios cancelToken?

时间:2020-06-09 04:02:23

标签: reactjs axios token

在ReactJs中,我使用Axios从API获取数据。尝试进行重复请求时,我需要使用 cancelToken 。例如:假设我在完成Axios请求之前就已经进入首页,则要求我进入“关于”页面。结果,React应用程序显示内存泄漏错误。因此,我的计划是在Axios拦截器中设置Axios cancelToken。我已经尝试过了,但是它对我不起作用。

requestApi.js

import axios from 'axios';

const requestApi = axios.create({
  baseURL: process.env.REACT_APP_API_URL
});
const source = axios.CancelToken.source();

requestApi.interceptors.request.use(async config => {
  const existUser = JSON.parse(localStorage.getItem('user'));
  const token = existUser && existUser.token ? existUser.token : null;
  if (token) {
    config.headers['Authorization'] = token;
    config.headers['cache-control'] = 'no-cache';
  }

  config.cancelToken = source.token;

  return config;
}, error => {
  return Promise.reject(error);
});

requestApi.interceptors.request.use(async response => {
  throw new axios.Cancel('Operation canceled by the user.');
  return response;
}, error => {
  return Promise.reject(error);
});

export default requestApi;

Dashboard.js

import requestApi from './requestApi';

useEffect(() => {
  const fetchData = async () => {
    try {
      const res = await requestApi.get('/dashboard');
      console.log(res.data);
    } catch (error) {
      console.log(error);
    }
  }

  fetchData();
}, []);

2 个答案:

答案 0 :(得分:1)

以防万一您仍然需要它或者其他人来寻找它。这就是它对我有用的方式。

import axios from "axios";

// Store requests
let sourceRequest = {};

const requestApi = axios.create({
  baseURL: process.env.REACT_APP_API_URL
});

requestApi.interceptors.request.use(
  async config => {
    const existUser = JSON.parse(localStorage.getItem("user"));
    const token = existUser && existUser.token ? existUser.token : null;
    if (token) {
      config.headers["Authorization"] = token;
      config.headers["cache-control"] = "no-cache";
    }

    return config;
  },
  error => {
    return Promise.reject(error);
  }
);

requestApi.interceptors.request.use(
  request => {
    // If the application exists cancel
    if (sourceRequest[request.url]) {
      sourceRequest[request.url].cancel("Automatic cancellation");
    }

    // Store or update application token
    const axiosSource = axios.CancelToken.source();
    sourceRequest[request.url] = { cancel: axiosSource.cancel };
    request.cancelToken = axiosSource.token;

    return request;
  },
  error => {
    return Promise.reject(error);
  }
);

export default requestApi;

答案 1 :(得分:0)

这可能不是一个稳定的解决方案,但我们可以使用一些魔法来制作一个组件,当组件卸载时终止其中运行的异步代码(包括请求)。无需令牌即可使其工作。查看Live Demo

import React, { useState } from "react";
import { useAsyncEffect, E_REASON_UNMOUNTED } from "use-async-effect2";
import { CanceledError } from "c-promise2";
import cpAxios from "cp-axios";

function* makeAPICall(url) {
  const existUser = JSON.parse(localStorage.getItem("user"));
  const token = existUser && existUser.token ? existUser.token : null;
  return yield cpAxios(url, {
    headers: {
      Authorization: token,
      "cache-control": "no-cache"
    }
  });
}

export default function TestComponent(props) {
  const [text, setText] = useState("");

  const cancel = useAsyncEffect(
    function* () {
      console.log("mount");

      this.timeout(props.timeout);

      try {
        setText("fetching...");
        const response = yield* makeAPICall(props.url);
        setText(`Success: ${JSON.stringify(response.data)}`);
      } catch (err) {
        CanceledError.rethrow(err, E_REASON_UNMOUNTED); //passthrough
        setText(`Failed: ${err}`);
      }

      return () => {
        console.log("unmount");
      };
    },
    [props.url]
  );

  return (
    <div className="component">
      <div className="caption">useAsyncEffect demo:</div>
      <div>{text}</div>
      <button onClick={cancel}>Abort</button>
    </div>
  );
}