Search code examples
reactjsreduxrefresh-tokenredux-promise

Recursive Action Call in Reactjs


I have a scenario for implementing refresh auth token. In this scenario, I've implemented a general action for each kind of actions (Post,Get, Delete) and call them with parameters.

export function Get(param) {
return function (dispatch) {
    var query = param ? !!param.Query ? param.Query : "" : "";
    var funtionName = param ? param.FunctionName : "";
    var url = endPointUrl + funtionName;
    var offset = param.Offset ? param.Offset : "0";
    var limit = param.Limit ? param.Limit : "10";
    const config = { headers: { 'Authorization': 'Bearer ' + sessionStorage.getItem('access-token') } };
    return new Promise((resolve, reject) => {
        axios.get(url, config).then((response) => {
            dispatch({ type: 'FETCH_SUCCEED_' + param.Caller, payload: response.data })
            resolve(response.data);
        }).catch((error) => {
                if (error.request.status == "401" && error.request.statusText == "RB.Exception.TokenExpiredException") {
                    refreshToken().then(() => {
                        dispatch(Get(param));
                    });
                }
            else {
                dispatch({ type: 'FETCH_ERROR_' + param.Caller, payload: error })
                reject(error);
            }

        })
    })
}

whenever I receive TokenExpiredException, I call refreshToken() and then call the current action again (recursively), so I can't use "then" in my component. do you have any solution about using "promise" or "then"? I need to render some messages in component after action finished.


Solution

  • Something like this?

    export function Get(param) {
        return function (dispatch) {
            var query = param ? !!param.Query ? param.Query : "" : "";
            var funtionName = param ? param.FunctionName : "";
            var url = endPointUrl + funtionName;
            var offset = param.Offset ? param.Offset : "0";
            var limit = param.Limit ? param.Limit : "10";
            const config = { headers: { 'Authorization': 'Bearer ' + sessionStorage.getItem('access-token') } };
            return new Promise((resolve, reject) => {
                axios.get(url, config).then((response) => {
                    dispatch({ type: 'FETCH_SUCCEED_' + param.Caller, payload: response.data })
                    resolve(response.data);
                }).catch((error) => {
                    if (error.request.status == "401" && error.request.statusText == "RB.Exception.TokenExpiredException") {
                        resolve(withRefresh(dispatch, param));
                    }
                    else {
                        dispatch({ type: 'FETCH_ERROR_' + param.Caller, payload: error })
                        reject(error);
                    }
    
                })
            })
        }
    }
    
    function withRefresh(dispatch, param) {
        return refreshToken().then(() => {
            return dispatch(Get(param));
        });
    }