Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RTK query interceptor multiple requests

I am having a problem with the RTK query interceptor, I implemented Automatic re-authorization by extending fetchBaseQuery​ per RTK query documentation and now I have a problem that if multiple requests get fired and the token is not valid all of them will get 401 as a response and all of them will try to refresh a token which will result in the first one being successful and other ones will fail and then the else will fire and return the user to log in screen.

Is there a way to prevent this?

  let result = await baseQuery(args, api, extraOptions)
      if (result.error && result.error.status === 401) {
        // try to get a new token
        const refreshResult = await baseQuery(
          {
          url: `http://.../${refreshToken}`,
          method: 'POST'
          }, 
          api, 
          extraOptions
        );
        if (refreshResult.data) {
          // store the new token
          api.dispatch(tokenReceived(refreshResult.data))
          // retry the initial query
          result = await baseQuery(args, api, extraOptions)
        } else {
          api.dispatch(loggedOut())
        }
      }
      return result
like image 572
Brixi Avatar asked Oct 19 '25 02:10

Brixi


1 Answers

One possible solution for that would be to use a mutex. We were discussing a possible solution for that in this github discussion:

import { Mutex } from 'async-mutex';

const mutex = new Mutex();

const baseQueryWithReauth = async (args, api, extraOptions) => {
  await mutex.waitForUnlock();
  let result = await baseQuery(args, api, extraOptions);

  if (result.error && result.error.status === 401) {
    if (!mutex.isLocked()) {
      const release = await mutex.acquire();

      try {
        const refreshResult = await baseQuery(
          {
            url: 'auth/refresh/',
            method: 'POST',
            body: { getToken(), getRefreshToken() },
          },
          api,
          extraOptions,
        );

        if (refreshResult.data) {
          api.dispatch(tokenUpdated(refreshResult.data));

          // retry the initial query
          result = await baseQuery(args, api, extraOptions);
        } else {
          api.dispatch(logout());
        }
      } finally {
        release();
      }
    } else {
      await mutex.waitForUnlock();
      result = await baseQuery(args, api, extraOptions);
    }
  }

  return result;
};

const baseApi = createApi({
  baseQuery: baseQueryWithReauth,
  endpoints: () => ({}),
});
like image 78
phry Avatar answered Oct 21 '25 08:10

phry



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!