ax ios сообщение об ошибке, возвращающее ошибку, запрещающее доступ к результатам - PullRequest
2 голосов
/ 26 апреля 2020

Я новичок в использовании JS фреймворков. Итак, у меня есть встроенная аутентификация, встроенная в FastAPI с использованием Python. Он обрабатывает создание токена доступа JWT, чтобы пользователь мог взаимодействовать с моим интерфейсом React.

Вот клиент, который я создал для вызова этого API (не уверен, является ли клиент правильным термином в 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
    })
}

Я поместил оператор console.log внутри исполнителя обещания, который будет регистрировать данные, возвращенные из моего вызова API. Однако этот журнал никогда не возвращается, скорее я вижу на консоли:

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

Я также немного новичок в концепции Обещаний, но это, по-видимому, никогда не входит в мое обещание 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='/' />
    )} />
);

1 Ответ

1 голос
/ 26 апреля 2020

Ошибки вызовут блок 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. Причина, по которой вы столкнулись с проблемой, заключается в том, что Обещания правдивы по своей природе, и вы выполняли троичную операцию из Обещания, а не из значения из обещания.

Асинхронный код работает, немедленно возвращая обещание, которое является по существу, это ценность. В какой-то момент обещание приведет к значению, но вы не можете рассчитывать на то, что оно будет значением в синхронном коде, поэтому вы должны установить состояние, которое позволит вашему компоненту знать, каким будет значение.

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="/" />
        );
      }}
    />
  );
};
...