我正在尝试创建获取令牌的 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
使用
async/await
和 Promise 链有点像 Javascript 反模式。我看到的另一个潜在问题是您的中间件不会返回为下一个中间件调用 next(action)
的结果。
通过使用
async/await
,您可以展平您在 getToken
Promise 链中捆绑的嵌套逻辑。
建议:
action.type
匹配时运行令牌提供程序和令牌获取逻辑await
并将tokenProvider.getToken
的结果赋值给token
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);
};