Di aplikasi saya, saya menjalankan setiap permintaan melalui middleware api. Saya mencoba membuat fungsi coba ulang middleware, ketika meminta dengan Otorisasi sedang terjadi dan memiliki token yang kedaluwarsa. Inilah middleware API saya saat ini:

const apiMiddleware = ({ dispatch }) => next => action => {
  next(action);
  // creating request data and params

  const retryRequest = () => {
    // refresh tokens with method: dispatch(getTokens());
    // retry initial request
  };

  axios({
    method,
    url,
    headers,
    [dataOrParams]: data,
  })
    .then(({ data: apiData }) => {
      dispatch(onSuccess(apiData));
    })
    .catch(error => {
      if (withToken && error.response.status === 401) {
        retryRequest();
      }
      return dispatch(apiError(label, error));
    })
};

export default apiMiddleware;

Ketika saya memanggil metode retryRequest() permintaan getTokens() dimulai, tetapi pada saat yang sama memulai permintaan awal, dan Redux belum diperbarui dengan token penyegaran baru, dan permintaan gagal lagi, karena getTokens() belum selesai.

Saya mengerti bahwa saya melakukannya dengan cara yang salah, solusi apa lagi yang bisa saya coba? Sehingga permintaan pertama getTokens() dipanggil dan diselesaikan maka permintaan awal dapat dilanjutkan.

1
Valerxx22 7 Juli 2020, 20:22

1 menjawab

Jawaban Terbaik

Jika Anda dapat membuat retryRequest() dan fungsi catch async, Anda dapat menggunakan

if(withToken && error.reponse.status === 401)
  await retryRequest();
return dispatch(apiError(label, error));

Jika Anda tidak bisa, kembalikan saja janji dari permintaan coba lagi dan

if(withToken && error.response.status === 401)
  return retryRequest().then(_=> dispatch(apiError(label, error)))
return dispatch(apiError(label, error))

Anda juga bisa menggunakan pencegat aksios, ini yang saya gunakan dalam proyek terbaru saya

api.interceptors.response.use(
  function (response) {
    response.data = parseResponseData(response.data);
    return response;
  },
  async function (error) {
    if (!error.response)
      Ant.message.error('Não foi possivel se conectar com o servidor');
    else if (
      error.response.status === 500 &&
      window.location.pathname !== '/erro/500'
    ) {
      if ((error.config.method as string).toLowerCase() === 'get')
        navigate('/erro/500');
      else
        Ant.message.error(
          'Desculpe, parece que algo deu errado no servidor.',
        );
    } else if (error.response.status === 401) {
      let request = error.config;
      const auth = localStorage.getItem('auth');
      let refreshToken = auth && JSON.parse(auth)['refreshToken'];
      var authService = new AuthService();
      return await authService
        .refresh(refreshToken)
        .then(async (resp) => {
          store.dispatch(login(resp.data));
          let axiosInstance = axios.create();
          intercept(axiosInstance);
          return await axiosInstance.request(request);
        })
        .catch((e) => {
          if (
            window.location.pathname !== '/login' &&
            (!e.response || e.response.status === 401)
          )
            navigate('/login');
        });
    }
    return error.response;
  },
);

Ini telah bekerja dengan cukup baik sejauh ini.

1
Arthur Bruel 7 Juli 2020, 21:23