如何使用axios和redux在Reactjs中创建用于刷新令牌的中间件

时间:2020-04-28 16:51:29

标签: reactjs react-redux axios

我正在使用Reactjs的前端,问题是在一定时间段后accessToken过期并且服务器发送状态为401(未授权),然后我需要将刷新令牌发送回服务器,它工作正常,直到我手动发送刷新令牌我设置了setInterval函数,但这并不是在令牌过期时如何自动发送它的好方法。 我也用谷歌搜索,但是每个人都在谈论创建中间件。我创建了它,但是这对我不起作用,但是当服务器发送状态为401然后运行中间件但它分派了我的refreshToken()函数

const customMiddleWare = store => next => action => {
  axios.interceptors.response.use(function (response) {
    return response;
  }, function (error) {
    if(error.status === 401) {
      // do something when unauthorized
      store.dispatch(refreshToken());
    }
    return Promise.reject(error);
  });
  console.log("Middleware triggered:", action);
  next(action);
}

顺便说一句,我正在使用redux,redux-thunk和axios。谢谢,

1 个答案:

答案 0 :(得分:1)

前一段时间,我曾经使用另一种方式:

首先,我创建了一些api文件夹,其中每个函数都为axios请求返回数据

// /api.js

export function signIn (data) {
  return {
    method: 'post',
    api: '/sign-in'
    data: data
  }
}

export function signUp (data) {
  return {
    method: 'post',
    api: '/registration'
    data: data
  }
}

然后我通过特定规则生成操作类型,例如:SIN_IN_REQUEST,其中:SIGN_IN表示/api.js中的signIn函数; REQUEST表示您需要执行api请求。结果,我的中间件看起来像下一个:

// request middleware

const instance = axios.create({
  baseURL: '/api'
});

function camelize(str) {
  return str.replace(/(?:^\w|[A-Z]|\b\w)/g, function(word, index) {
    return index === 0 ? word.toLowerCase() : word.toUpperCase();
  }).replace(/\s+/g, '');
}

const customMiddleWare = store => next => action => {
  if (!action.type.endsWith('_REQUEST')) {
    next();
    return;
  }

  const methodName = action.type.replace('_REQUEST', ''); // removed _REQUEST from action type
  const camelCaseMethodName = camelize(methodName); // the result is "signIn"
  const method = api[camelCaseMethodName];

  if (!method) {
    next();
    return;
  }

  const dataForRequest = method(action.payload);

  try {
    const response = await instance(dataForRequest);

    const newActionType = action.type.replace('_REQUEST', '_SUCCESS');

    dispatch({
      type: newActionType,
      payload: {
        requestPayload: action.payload,
        response: response,
      }
    })
  } catch(error) {
    if (error.status === '401') {
      dispatch(refreshToken());
      next();
      return;
    }

    const newActionType = action.type.replace('_REQUEST', '_FAILURE');
    dispatch({
      type: newActionType,
      payload: {
        requestPayload: action.payload,
        error: error,
      }
    })
  }

  next();
}

之后,您可以像这样轻松地管理应用程序中的任何api请求:

function someTHunkMethod(username, password) {
  return (dispatch, getState) => {
    dispatch({
      type: 'SIGN_IN_REQUEST',
      payload: {
        username,
        password
      }
    })
  }
}

function oneMoreThunk(data) {
  return (dispatch, getState) => {
    dispatch({
      type: 'GET_USERS_REQUEST',
      payload: data
    })
  }
}

然后在reducer中做类似的事情

...

switch (action.type) {
    case 'SIGN_REQUEST':
      return {
        isLoading: true,
        user: null
      }
    case 'SIGN_SUCCESS':
      return {
        isLoading: false,
        user: action.payload.response.data
      }
    case 'SIGN_FAILURE':
      return {
        isLoading: false,
        user: null
      }
    default:
      return state
  }