RTK查询拦截器多个请求

Bri*_*ixi 3 reactjs redux react-redux redux-toolkit rtk-query

我的 RTK 查询拦截器有问题,我通过扩展每个RTK 查询文档的fetchBaseQuery\xe2\x80\x8b 来实现自动重新授权,现在我遇到的问题是,如果触发多个请求并且令牌无效,则所有他们将收到 401 作为响应,并且所有人都将尝试刷新令牌,这将导致第一个成功,其他令牌将失败,然后其他将触发并使用户返回登录屏幕。

\n

有办法防止这种情况吗?

\n
  let result = await baseQuery(args, api, extraOptions)\n      if (result.error && result.error.status === 401) {\n        // try to get a new token\n        const refreshResult = await baseQuery(\n          {\n          url: `http://.../${refreshToken}`,\n          method: \'POST\'\n          }, \n          api, \n          extraOptions\n        );\n        if (refreshResult.data) {\n          // store the new token\n          api.dispatch(tokenReceived(refreshResult.data))\n          // retry the initial query\n          result = await baseQuery(args, api, extraOptions)\n        } else {\n          api.dispatch(loggedOut())\n        }\n      }\n      return result\n
Run Code Online (Sandbox Code Playgroud)\n

phr*_*hry 5

一种可能的解决方案是使用互斥体。我们在此 github 讨论中讨论了一个可能的解决方案:

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: () => ({}),
});
Run Code Online (Sandbox Code Playgroud)