axios post 承诺返回错误,不允许访问结果

axios post promise returning error disallowing accessing result

我是 JS 框架的新手。因此,我使用 Python 在 FastAPI 中构建了一个身份验证后端。它处理为用户创建 JWT 访问令牌以与我的 React 前端交互。

这是我创建的用来调用 API 的客户端(不确定 Client 是否是 JS 中的正确术语)。

export const authApi = {
  /**
   * Retrieves the JWT access token of registered user.
   * @param {string} username - Username of attempting user.
   * @param {string} password - Password of attempting user.
   */
  async logInGetToken(username, password) {
    const params = new URLSearchParams();
    params.append('username', username);
    params.append('password', password);
    return axios.post(`${apiUrl}/api/v1/login/access-token`, params);
  },
  /**
   * Pings authentication server to determine whether access token is valid.
   * @param {*} token - API token provided via Authentication API.
   */
  async isActiveToken(token) {
    return axios.post(`${apiUrl}/api/v1/login/test-token`, authHeaders(token));
  },
  ...
}

我现在正在尝试构建一个验证处理程序来访问访问令牌是否仍未过期。这是我为此生成的代码:

const isAuthenticated = () => {
    return authApi.isActiveToken(
        localStorage.getItem('token')
    ).then(res => {
        console.log(res)
        if (res.status > 400) {
            return false
        }
        return true
    })
}

我在 promise 执行器中放置了一个 console.log 语句,它将记录从我的 API 调用返回的数据。但是,此日志永远不会返回,而是我在控制台上看到:

POST http://localhost:8000/api/v1/login/test-token 401 (Unauthorized)

我对 Promises 的概念也有点陌生,但这似乎从未进入我的 promise then 块。有什么建议吗?

谢谢!


如果对您有帮助,请在此处使用 isAuthenticated

const AuthenticatedRoute = ({ component: Component, ...rest }) => (
    <Route {...rest} render={(props) => (
        isAuthenticated()
            ? <Component {...props} />
            : <Redirect to='/login' />
    )} />
);

const UnauthenticatedRoute = ({ component: Component, ...rest }) => (
    <Route {...rest} render={(props) => (
        !isAuthenticated()
            ? <Component {...props} />
            : <Redirect to='/' />
    )} />
);

错误将触发 promise 链上的 catch 块,而不是 then 块的第一个参数。

const isAuthenticated = () => {
  return authApi.isActiveToken(localStorage.getItem('token')).then(
    (res) => {
      console.log(res);
      if (res.status > 400) {
        return false;
      }
      return true;
    },
    (error) => {
      return false;
    }
  );
};

或者作为单独的 catch 块:

const isAuthenticated = () => {
  return authApi
    .isActiveToken(localStorage.getItem('token'))
    .then((res) => {
      console.log(res);
      if (res.status > 400) {
        return false;
      }
      return true;
    })
    .catch((error) => {
      return false;
    });
};

使用 async/await 的另一种可能性,我倾向于使用它,因为它更易于阅读,但它可能会造成混淆,因为它会将自己伪装成看起来更像同步代码。

const isAuthenticated = async () => {
  try {
    await authApi
    .isActiveToken(localStorage.getItem('token'))
    return true;
  } catch (error) {
    return false;
  }
};

编辑:以下是修改代码以允许 isAuthenticated 调用的异步特性的方法。您 运行 陷入问题的原因是因为 Promise 本质上是真实的,并且您正在根据 Promise 而不是 Promise 的值执行三元运算。

异步代码通过立即返回本质上是一个值的承诺来工作。在某些时候,promise 会产生一个值,但您不能指望它是同步代码中的一个值,因此您必须设置一个状态,让您的组件知道该值最终是什么。

import { useEffect, useState } from 'react';

const isAuthenticated = async () => {
  try {
    await authApi.isActiveToken(localStorage.getItem('token'));
    return true;
  } catch (error) {
    return false;
  }
};

const AuthenticatedRoute = ({ component: Component, ...rest }) => {
  const [authenticated, setAuthenticated] = useState();
  useEffect(() => {
    isAuthenticated().then((authenticated) => {
      setAuthenticated(authenticated);
    });
  });
  return (
    <Route
      {...rest}
      render={(props) => {
        return authenticated === undefined ? (
          'Loading...'
        ) : authenticated ? (
          <Component {...props} />
        ) : (
          <Redirect to="/" />
        );
      }}
    />
  );
};

const UnauthenticatedRoute = ({ component: Component, ...rest }) => {
  const [authenticated, setAuthenticated] = useState();
  useEffect(() => {
    isAuthenticated().then((authenticated) => {
      setAuthenticated(authenticated);
    });
  });
  return (
    <Route
      {...rest}
      render={(props) => {
        return authenticated === undefined ? (
          'Loading...'
        ) : !authenticated ? (
          <Component {...props} />
        ) : (
          <Redirect to="/" />
        );
      }}
    />
  );
};