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

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

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

问题

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

privateAxios.interceptors.response.use(
  (response) => {
    return response;
  },
  (error) => {
    const { config, response } = error;
    const originalRequest = config;
    if (response?.status === 401) {
      apiProvider
        .refreshToken()
        .then(() => {
          let headers = getAuthHeaders();
          privateAxios.defaults.headers = headers;
          originalRequest.headers = headers;
          return privateAxios(originalRequest);
        })
        .catch((err) => {
          logout();
          return Promise.reject(err);
        });
    }
    return Promise.reject(error);
  }
);

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

api.post(data)
  .then(() => {
    showSuccessFeedbackForm();
    reloadTable();
    handleClose();
  })
  .catch((error) => {
    setAlertInfos({
      message: JSON.stringify(error.response.data),
      severity: "error",
    });
    setShowAlert(true);
  })
  .finally(() => {
    setIsLoaded(true);
  });

我的问题是,如果需要刷新令牌(当代码到达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:

privateAxios.interceptors.response.use(
  (response) => {
    return response;
  },
  (error) => {
    const { config, response } = error;
    const originalRequest = config;
    if (response?.status === 401) {
      apiProvider
        .refreshToken()
        .then(() => {
          let headers = getAuthHeaders();
          privateAxios.defaults.headers = headers;
          originalRequest.headers = headers;
          return privateAxios(originalRequest);
        })
        .catch((err) => {
          logout();
          return Promise.reject(err);
        });
    }
    return Promise.reject(error);
  }
);

On my component I have the following:

api.post(data)
  .then(() => {
    showSuccessFeedbackForm();
    reloadTable();
    handleClose();
  })
  .catch((error) => {
    setAlertInfos({
      message: JSON.stringify(error.response.data),
      severity: "error",
    });
    setShowAlert(true);
  })
  .finally(() => {
    setIsLoaded(true);
  });

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);,导致前端收到拒绝而不是解析。

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

axios.interceptors.response.use(
  (res) => res,
  (err) => {
    console.log("##### AXIOS ERROR #####");
    dispatch(increment());
  }
);

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

axios.interceptors.response.use(
  (res) => res,
  (err) => {
    console.log("##### AXIOS ERROR #####");
    return Promise.reject();
  }
);
英文:

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":

axios.interceptors.response.use(
  (res) => res,
  (err) => {
    console.log("##### AXIOS ERROR #####");
    dispatch(increment());
  }
);

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

axios.interceptors.response.use(
  (res) => res,
  (err) => {
    console.log("##### AXIOS ERROR #####");
    return Promise.reject();
  }
);

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:

确定