React + axios拦截器: 在组件上下文中重试原始请求

huangapple go评论96阅读模式
英文:

React + axios interceptors: retry original request within component's context

问题

我正在学习React,使用axios和JWT进行身份验证。我已经编写了一个拦截器以自动刷新令牌:

  1. privateAxios.interceptors.response.use(
  2. (response) => {
  3. return response;
  4. },
  5. (error) => {
  6. const { config, response } = error;
  7. const originalRequest = config;
  8. if (response?.status === 401) {
  9. apiProvider
  10. .refreshToken()
  11. .then(() => {
  12. let headers = getAuthHeaders();
  13. privateAxios.defaults.headers = headers;
  14. originalRequest.headers = headers;
  15. return privateAxios(originalRequest);
  16. })
  17. .catch((err) => {
  18. logout();
  19. return Promise.reject(err);
  20. });
  21. }
  22. return Promise.reject(error);
  23. }
  24. );

在我的组件中,我有以下内容:

  1. api.post(data)
  2. .then(() => {
  3. showSuccessFeedbackForm();
  4. reloadTable();
  5. handleClose();
  6. })
  7. .catch((error) => {
  8. setAlertInfos({
  9. message: JSON.stringify(error.response.data),
  10. severity: "error",
  11. });
  12. setShowAlert(true);
  13. })
  14. .finally(() => {
  15. setIsLoaded(true);
  16. });

我的问题是,如果需要刷新令牌(当代码到达return privateAxios(originalRequest)时),我想继续组件的正常“流程”(即,showSuccessFeedbackForm()reloadTable()handleClose())。我该如何实现这一点?

英文:

I'm learning React and I'm using axios and JWT for authentication. I have written an interceptor to refresh the token automatically:

  1. privateAxios.interceptors.response.use(
  2. (response) => {
  3. return response;
  4. },
  5. (error) => {
  6. const { config, response } = error;
  7. const originalRequest = config;
  8. if (response?.status === 401) {
  9. apiProvider
  10. .refreshToken()
  11. .then(() => {
  12. let headers = getAuthHeaders();
  13. privateAxios.defaults.headers = headers;
  14. originalRequest.headers = headers;
  15. return privateAxios(originalRequest);
  16. })
  17. .catch((err) => {
  18. logout();
  19. return Promise.reject(err);
  20. });
  21. }
  22. return Promise.reject(error);
  23. }
  24. );

On my component I have the following:

  1. api.post(data)
  2. .then(() => {
  3. showSuccessFeedbackForm();
  4. reloadTable();
  5. handleClose();
  6. })
  7. .catch((error) => {
  8. setAlertInfos({
  9. message: JSON.stringify(error.response.data),
  10. severity: "error",
  11. });
  12. setShowAlert(true);
  13. })
  14. .finally(() => {
  15. setIsLoaded(true);
  16. });

My problem is that I want to continue with the component's normal "flow" (i.e., showSuccessFeedbackForm() and reloadTable() and handleClose()) if the token needed to be refreshed (when the code reaches return privateAxios(originalRequest)).

How can I accomplish this?

答案1

得分: 2

只需要将 apiProvider.refreshToken() 调用处的 return 修改为 return。在 return privateAxios(originalRequest); 返回后,执行 return Promise.reject(error);,导致前端收到拒绝而不是解析。

考虑到这种拦截到的错误,不会抛出错误到前端,仍然会“解析”:

  1. axios.interceptors.response.use(
  2. (res) => res,
  3. (err) => {
  4. console.log("##### AXIOS ERROR #####");
  5. dispatch(increment());
  6. }
  7. );

将其更改为以下内容将导致前端捕获错误,这实际上是您的代码所做的:

  1. axios.interceptors.response.use(
  2. (res) => res,
  3. (err) => {
  4. console.log("##### AXIOS ERROR #####");
  5. return Promise.reject();
  6. }
  7. );
英文:

It looks like you should just have to return the apiProvider.refreshToken()... call. After return privateAxios(originalRequest); returns, then return Promise.reject(error); is executing which causes the front-end to receiving an rejection not a resolution.

Consider this intercepted error which does not throw an error to the frontend which still "resolves":

  1. axios.interceptors.response.use(
  2. (res) => res,
  3. (err) => {
  4. console.log("##### AXIOS ERROR #####");
  5. dispatch(increment());
  6. }
  7. );

Simply changing it to this causes the front-end to catch an error which is what your code is essentially doing:

  1. axios.interceptors.response.use(
  2. (res) => res,
  3. (err) => {
  4. console.log("##### AXIOS ERROR #####");
  5. return Promise.reject();
  6. }
  7. );

huangapple
  • 本文由 发表于 2023年2月10日 05:47:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/75404750.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定