我们可以使用 axios 拦截器来响应 window.fetch 发出的 http 调用吗?

Can we use axios interceptor for http calls made by window.fetch in react?

我们的 React 应用在其大部分或所有区域中使用 window.fetch 方法进行 http 调用。以前,它只有一个访问内容的令牌,而我们所做的是,我们在每个请求中单独添加一个 header,以发送令牌等。下面是此类请求的示例代码:

useEffect(() => {
    // GET S3 CREDANTIONS
    fetch("/dashboard/de/question/s3credentials", {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${loginReducer}`,
      },
    })

但现在我们已经配置 api 访问两个令牌,一个用于访问内容,另一个用于刷新访问令牌。为此,在从互联网上搜索之后,我们决定添加一个 axios 拦截器,以在每次 http 调用之前检查 access_token 是否有效。 所以,我制作了拦截器并将其放在反应应用程序的 index.js 中。如果 access_token 有效,则在发送之前全局检查每个 http 请求;如果不是,请刷新。我从这个 link 得到了这个想法: https://blog.bitsrc.io/setting-up-axios-interceptors-for-all-http-calls-in-an-application-71bc2c636e4e 除了这个link,我还从包括Whosebug在内的许多其他网站上学习了它,并且我对它的理解更多,所以应用了它。 下面是 index.js 文件中的 axios 拦截器的代码(整体):

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import axios from "axios";
import AdminIndex from "./AdminPanel/Pages/AdminIndex";
import Cookies from "js-cookie";
// React Redux
import allReducers from "./reducers/index";
import { createStore } from "redux";
import { Provider } from "react-redux";
import StateLoader from "./reducers/PresistedState";
const stateLoader = new StateLoader();

let store = createStore(
  allReducers,
  stateLoader.loadState(),
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
axios.interceptors.request.use(
  async (config) => {
    let serverCallUrl = new URL(config.url);
    if (serverCallUrl.pathname.includes("/superuser/login")) return config;
    let access_token = Cookies.get("access");
    let refresh_token = localStorage.getItem("refresh_token");

    await AdminIndex.hasAccess(access_token, refresh_token);

    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);
store.subscribe(() => {
  stateLoader.saveState(store.getState());
});

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

我认为 axios 拦截器存在一些问题。因为当我启动应用程序并输入登录凭据时,应用程序显示错误的用户名和密码等。我想知道问题是否是因为我们的应用程序使用的是 fetch 方法而不是 axios?因为我们正在尝试为获取 http 调用实现 axios 拦截器。仅对于登录代码,我们已应用 axios 对用户进行身份验证。下面是login的handleSubmit函数:

  const handleSubmit = async (e) => {
    e.preventDefault();

    axios({
      method: "post",
      url: "/superuser/login",
      headers: {
        "content-type": "application/x-www-form-urlencoded;charset=utf-8",
      },
      data: `username=${values.username}&useremail=${values.useremail}`,
    })
      .then((res) => {
        const { access_token, refresh_token } = res.data;
        Cookies.set("access", access_token);
        localStorage.setItem("refresh_token", refresh_token);
        props.set_login(res.data.access_token);
        history.push("/admin/panel/papers");
      })
      .catch((err) => setDialogStatus(true));
  };

请查看是什么导致无法登录应用程序的错误。如果我删除拦截器,应用程序会成功登录,但是当 access_token 过期时我将无法刷新它。在拦截器中,我将刷新 access_token 的功能放入应用程序的道具中。希望我已经清楚地说明了我的问题。但如果有什么遗漏,请不要屏蔽问题,只需添加评论,我会立即回复。 提前致谢!

没有! axios拦截器是axios的内部机制;这意味着,它只拦截由 axios 库本身发送的请求。如果我们想拦截 window.fetch 请求,我们需要为此设置自定义拦截器,例如,如果 api 的响应是 403 错误,则在 catch 块中进行过滤,然后执行特定操作。 但即便如此,最优选的方法是完全使用 axios 库并在整个项目中进行替换。