【问题标题】:run response interceptor only once when multiple API calls多个 API 调用时仅运行一次响应拦截器
【发布时间】:2016-09-15 10:52:39
【问题描述】:

我有一个这样的拦截器

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)
        })
      } 
  })

一切正常,但如果我喜欢在一个 React 组件上调用 4 个 API,并且发生此错误,则相同的代码将运行 4 次,这意味着我将发送 4 次刷新令牌并获取身份验证令牌,我显然只想运行一次

【问题讨论】:

    标签: javascript asynchronous reactjs promise axios


    【解决方案1】:

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

    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);
       });
      } 
    });
    

    希望对你有帮助;)

    【讨论】:

    • 为什么 resetAuthTokenRequest 在 .then() 中被调用了两次?
    • 在任何一种情况下(即成功或失败)都使身份验证请求承诺对象无效。
    【解决方案2】:

    您是否考虑过请求的节流/去抖动包装器? 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(

    【讨论】:

    • debounce 在这 1000 毫秒内是否会丢弃后续呼叫?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-25
    • 2013-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-14
    • 1970-01-01
    相关资源
    最近更新 更多