首页 > 解决方案 > 使用 axios 处理 API 错误响应(多个文件)

问题描述

我是 React 的新手,我试图将我的 Axios http 实用程序分隔在不同的文件中。

如果我使用正确的凭据登录,它可以正常工作,但是当我尝试错误的凭据并且我的 API 响应带有 401(坏凭据)消息时,Axios 会执行该then()方法而不是该catch()方法。

axios.ts

import Axios from "axios";

const JSON_CONTENT_TYPE = "application/json";

// axios configuration
const axios = Axios.create({
  baseURL: process.env.REACT_APP_API_URL,
  responseType: "json"
});

// ... other requests handlers

export const post = <T = any>(
  url: string,
  body: any,
  params?: any,
  contentType = JSON_CONTENT_TYPE
) => {
  return axios.post<T>(url, body, {
    params,
    headers: { "Content-Type": contentType }
  });
};

登录适配器.ts

import { ILogin } from "../../model/login.model";
import * as Http from "../axios";
import * as StorageManager from "../storage-manager";

type TokenBody = {
  id_token: string;
};

export const login = (credentials: ILogin) => {
  return new Promise((resolve, reject) => {
    Http.post<TokenBody>("/authenticate", credentials)
      .then((resp) => {
        // Stores jwt in local/session storage.
        // HERE IS WHEN MY APP CRASHES, The error says 'resp is undefined' and THIS ERROR (not the response from my API) is caught by the catch method below.
        StorageManager.setToken(resp.data.id_token, credentials.rememberMe);
        // Does another request to get user info.
        Http.get("/account").then(console.log);
        resolve("Success");
      })
      .catch((error) => reject("Error, " + error.response.data)); // THIS SHOULD SEND THE ERROR MESSAGE TO LoginPage.tsx
  });
};

登录页面.tsx

import { FormEvent, useState } from "react";
import "../../styles/LoginPage.css";
import * as LoginAdapter from "../../adapters/loginAdapters/login-adapter";
import { RouteComponentProps } from "react-router-dom";

const LoginPage = ({history}: RouteComponentProps) = {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [rememberMe, setRememberMe] = useState(false);

  const submit = (e: FormEvent<HTMLFormElement>) => {
    LoginAdapter.login({ email, password, rememberMe })
      .then(() => {
        history.push("/admin/courses");
      })
      .catch((error) => {
        console.log(error);
      });
    e.preventDefault();
  }
  
  return (
    <form onSubmit={submit}>
      {/* <input ... email, password, and 'remember me' form fields.*/}
    </form>
  );
}

export default LoginPage;

当我直接从包中使用axios时。( import axios from "axios") 它工作得很好。但是我必须重写我的 api 端点、响应类型、拦截器等。我不知道为什么它不起作用,我错过了什么吗?

标签: reactjstypescriptaxios

解决方案


我的拦截器是问题所在,我没有注意到错误处理程序应该返回一个带有拒绝原因的 Promise。

axios.interceptors.response.use(
  (resp) => resp,
  (error) => {
  if (
    error.response.status === 401 &&
    error.response.config.url !== "/account"
  ) {
    LoginAdapter.logout();
  }
    // before: <nothing>
    // now:
    return Promise.reject(error);
  }
);

推荐阅读