当多个API调用时,只运行一次响应拦截器

run response interceptor only once when multiple API calls

本文关键字:一次 响应 运行 API 调用      更新时间:2023-09-26

我有一个像这样的拦截器

axios.interceptors.response.use(undefined, err=> {
    const error = err.response;
    console.log(error);
    if (error.status===401 && error.config && !error.config.__isRetryRequest) {
        return axios.post(Config.oauthUrl + '/token', 'grant_type=refresh_token&refresh_token='+refreshToken,
            { headers: {
          'Authorization': 'Basic ' + btoa(Config.clientId + ':' + Config.clientSecret),
          'Content-Type': 'application/x-www-form-urlencoded,charset=UTF-8'
         }
       })
        .then(response => {
          saveTokens(response.data)
          error.config.__isRetryRequest = true;
          return axios(error.config)
        })
      } 
  })

和一切都在工作,但如果我喜欢在我的情况下4个API调用一个React组件,这个错误发生相同的代码将运行4次,这意味着4次我将发送我的刷新令牌,并获得认证令牌,我想只运行一次显然

我认为您可以使用以下方式对身份验证请求进行排队:

let authTokenRequest;
// This function makes a call to get the auth token
// or it returns the same promise as an in-progress call to get the auth token
function getAuthToken() {
  if (!authTokenRequest) {
    authTokenRequest = makeActualAuthenticationRequest();
    authTokenRequest.then(resetAuthTokenRequest, resetAuthTokenRequest);
  }
  return authTokenRequest;
}
function resetAuthTokenRequest() {
  authTokenRequest = null;
}

然后在你的拦截器中…

axios.interceptors.response.use(undefined, err => {
  const error = err.response;
  if (error.status===401 && error.config && !error.config.__isRetryRequest) {
    return getAuthToken().then(response => {
      saveTokens(response.data);
      error.config.__isRetryRequest = true;
      return axios(error.config);
   });
  } 
});

您考虑过为请求使用节流/脱包器吗?Lodash内置了这两种功能。这里有一个很好的例子。

http://jsfiddle.net/missinglink/19e2r2we/

…也许你的案子需要这样的东西?

axios.interceptors.response.use(undefined, err=> {
    const error = err.response;
    console.log(error);
    if (error.status===401 && error.config && !error.config.__isRetryRequest) {
        return _.debounce(axios.post(Config.oauthUrl + '/token', 'grant_type=refresh_token&refresh_token='+refreshToken,
            { headers: {
          'Authorization': 'Basic ' + btoa(Config.clientId + ':' + Config.clientSecret),
          'Content-Type': 'application/x-www-form-urlencoded,charset=UTF-8'
         }
       })
        .then(response => {
          saveTokens(response.data)
          error.config.__isRetryRequest = true;
          return axios(error.config)
        }), 1000)
      } 
  })

可能这样更好?axios.interceptors.response.use(undefined, _.debounce(