如何使用自定义中间件在 RTK 查询之前获取令牌?

问题描述 投票:0回答:1

我正在尝试创建获取令牌的 Redux 中间件(最近将检查令牌是否过期,但出于测试目的,我现在只获取令牌)。每次 RTK-Query 开始其操作时。我的问题是,当我从 Azure 获取/获取令牌时,它是

async
并且花了一段时间才获取令牌,但我的中间件只是继续而不等待我的令牌,并且我没有获取令牌,不是在正确的时刻在 RTK 查询数据获取之前。也许我不太了解 Redux 和中间件中的异步逻辑。

authMiddleware.ts:

export const authMiddleware: Middleware =
  ({ dispatch, getState }) => next => async (action: PayloadAction) => {
    // const store = getState() as RootState;
    console.log('Dispatching action:', action.type);
    logWithTime('Middleware: action is a function and started');

    if (action.type === 'apiInvoices/config/middlewareRegistered') {
      logWithTime(
        'middleware in action: apiInvoices/config/middlewareRegistered'
      );
      let token: string | void = '';
      console.log('Action in if: ', action.type)
      const tokenProvider: AadTokenProvider = await getAadTokenProvider();

      if (tokenProvider) {
        logWithTime('Token provider set');
      }

      // check if tokenProvider is not null
      if (tokenProvider) {
        console.log('Token provider:', tokenProvider);
      } else {
        console.log('Token provider is null')
      }

      // fetch token, wait till token is fetched and then set
      // token in store then return next action
      token = await tokenProvider.getToken(
        '6cbc9b1e-901d-4a99-a947-ae36ffe3ac38'
      )
        .then(token => {
          setToken({ endpoint: 'getInvoiceByID', token: token })
        })
        .then(() => {
          logWithTime('Token fetched and set in store');
          next(action)
        });
    }
  };

store.ts:

import { configureStore } from '@reduxjs/toolkit';
import { tokenReducer } from '../slices/tokenSlice';
import { apiInvoices } from '../api/invoiceApi';
import logger from 'redux-logger';
import { authMiddleware } from '../middleware/authMiddleware/authMiddleware';

const store = configureStore({
  reducer: {
    token: tokenReducer,
    [apiInvoices.reducerPath]: apiInvoices.reducer,
    // other reducers
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({})
      .concat(apiInvoices.middleware, authMiddleware, logger),
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

export default store

这是一些控制台输出,我可以在其中看到我太晚获得令牌了:

Dispatching action: apiInvoices/config/middlewareRegistered authMiddleware.ts:15 [2024-11-14T08:06:58.937Z] Middleware: action is a function and started

authMiddleware.ts:15 [2024-11-14T08:06:58.937Z] middleware in action: apiInvoices/config/middlewareRegistered

authMiddleware.ts:25 Action in if: apiInvoices/config/middlewareRegistered

authMiddleware.ts:15 [2024-11-14T08:06:58.940Z] Token provider set

authMiddleware.ts:33 Token provider: e {_aadConfiguration: {…},
_oboConfiguration: {…}, _tokenAcquisitionEvent: e, onBeforeRedirectEvent: e, popupEvent: e, …}

authMiddleware.ts:19 Dispatching action: apiInvoices/executeQuery/pending

authMiddleware.ts:15 [2024-11-14T08:06:58.944Z] Middleware: action is a function and started

authMiddleware.ts:15 [2024-11-14T08:06:58.944Z] Middleware: action is a function and ended

authMiddleware.ts:42 action apiInvoices/executeQuery/pending @ 09:06:58.944
typescript redux react-redux
1个回答
0
投票

使用

async/await
Promise 链有点像 Javascript 反模式。我看到的另一个潜在问题是您的中间件不会返回为下一个中间件调用
next(action)
的结果。

通过使用

async/await
,您可以展平您在
getToken
Promise 链中捆绑的嵌套逻辑。

建议:

  • 仅在
    action.type
    匹配时运行令牌提供程序和令牌获取逻辑
  • 仅在令牌提供者可用时运行令牌获取逻辑
  • await
    并将
    tokenProvider.getToken
    的结果赋值给
    token
  • Always无条件返回调用结果
    next(action)
export const authMiddleware: Middleware = store => next => async (action) => {
  console.log('Dispatching action:', action.type);
  logWithTime('Middleware: action is a function and started');

  if (action.type === 'apiInvoices/config/middlewareRegistered') {
    logWithTime(
      'middleware in action: apiInvoices/config/middlewareRegistered'
    );
      
    console.log('Action in if: ', action.type)
    const tokenProvider: AadTokenProvider = await getAadTokenProvider();

    // check if tokenProvider is not null
    if (tokenProvider) {
      console.log('Token provider:', tokenProvider);
      logWithTime('Token provider set');

      // fetch token, wait till token is fetched and then set
      // token in store then return next action
      const token = await tokenProvider.getToken(
        '6cbc9b1e-901d-4a99-a947-ae36ffe3ac38'
      );

      setToken({ endpoint: 'getInvoiceByID', token: token });
      logWithTime('Token fetched and set in store');
    } else {
      console.log('Token provider is null')
    }
  }

  return next(action);
};
© www.soinside.com 2019 - 2024. All rights reserved.