【问题标题】:Axios Request Interceptor wait until ajax call finishesAxios 请求拦截器等到 ajax 调用完成
【发布时间】:2017-12-12 15:11:59
【问题描述】:

我有一个用于 axios 调用的请求拦截器。它会检查我的 jwt 令牌并在必要时调用刷新。

axios.interceptors.request.use((config) =>{

    const state = store.getState(); // get renewed state
    const time = Math.floor( new Date().getTime() / 1000 );

    if( 
        ! state.app.jwtRefreshOnRequest 
        && time >= state.jwt.expires - 120
        && state.jwt.refresh_before > time
    ){ // expiring in 2 min. refresh    

        //dispatch({type: 'JWT_REFRESH_REQUEST'});
        axios.get( API_BASE_URL + '/auth/refresh')
            .then(function(response){
                // dispatch({type: 'JWT_REFRESH_SUCCESS', payload: response.data});
                axios(config).then(resolve, reject);
            })
            .catch(function(err){               
                reject(err);
        });

    }       

    return config;
}); 

此代码正确调用刷新并保存新令牌,但原始调用在拦截器请求完成之前不会保持,因此使用过期令牌。

所以,我想我需要从拦截器进行同步调用。

【问题讨论】:

    标签: javascript ajax axios


    【解决方案1】:

    避免对 HTTP 请求进行同步调用,因为它们只会让您的应用程序挂起。

    您需要在这里做的是使调用代码异步 - 与任何回调、承诺或异步相关的一般规则是,一旦您异步,一切都需要异步。

    这里,axios.get 返回一个 Promise - 一个跟踪异步 HTTP 请求并在完成后解析的对象。您需要返回它,而不是 config

    我们通过返回一个新的Promise 来做到这一点 - 如果需要对新令牌的 HTTP 请求,它会等待它,如果不需要它可以立即resolve

    axios.interceptors.request.use(config =>
        new Promise((resolve, reject) => {
            // ... your code ...
    
            axios.get( API_BASE_URL + '/auth/refresh')
                .then(response => {
                    // Get your config from the response
                    const newConfig = getConfigFromResponse(response);
    
                    // Resolve the promise
                    resolve(newConfig);
                }, reject);
    
            // Or when you don't need an HTTP request just resolve
            resolve(config);
        })
    }); 
    

    每当您看到 then 时,您就在与 Promise 打交道,而一旦您一切都需要返回 Promise

    如果您可以使用async/await,这要容易得多 - 现代浏览器支持的新关键字,如果您需要支持旧用户,则可以转换。有了这些,您只需将 Promise 调用与 await 关键字内联。

    axios.interceptors.request.use(async config =>
    
        // ... your code ...
    
        if(/* We need to get the async token */) {
            const response = await axios.get( API_BASE_URL + '/auth/refresh');
            config = getConfigFromResponse(response);
        }
    
        return config;
    }); 
    

    【讨论】:

    • 不清楚 getConfigFromResponse(response) 是做什么的??
    • @ace 它将response 对象转换为config 格式- 这不是问题的一部分,因此实现取决于您。它可能是await response.json(),假设状态正常并且您添加了一个外部await。在这个答案中,它只是一个占位符。
    猜你喜欢
    • 2019-12-31
    • 2021-09-03
    • 2020-09-25
    • 2017-08-22
    • 1970-01-01
    • 2022-11-14
    • 2011-12-26
    • 2013-05-24
    • 2019-10-04
    相关资源
    最近更新 更多