You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将createAsyncThunk的结果传递给自定义Redux中间件?

Redux中间件如何获取createAsyncThunk异步完成后的结果

我的自定义Redux中间件需要依赖createAsyncThunk生成的fulfilled动作结果,但目前的问题是:中间件处于动作与reducer之间,只能通过getState()访问状态,而createAsyncThunk带来的状态更新要等reducer处理完动作后才会生效,此时中间件拿到的还是旧状态。

Redux执行流程

用户切片代码

// 获取用户列表
export const getUsers = createAsyncThunk(
  'users/getUsers',
  async (arg, { rejectWithValue }) => {
    try {
      const response = await axios.get('users');
      return response.data;
    } catch (error) {
      return rejectWithValue(error.response.data);
    }
  },
);

// 初始状态
const initialState = {
  users: [],
  isLoading: false,
  hasError: false,
  errorMessage: '',
};

const usersSlice = createSlice({
  name: 'users',
  initialState,
  extraReducers: builder => {
    builder
      .addCase(getUsers.pending, (state, action) => {
        state.isLoading = true;
        state.hasError = false;
        state.errorMessage = false;
      })
      .addCase(getUsers.fulfilled, (state, action) => {
        state.users = action.payload.users;
        state.isLoading = false;
        state.hasError = false;
      })
      .addCase(getUsers.rejected, (state, action) => {
        state.errorMessage = action.payload.message;
        state.isLoading = false;
        state.hasError = true;
      })
  },
});

自定义中间件代码

const customMiddleware = store => next => action => {
  // 这里拿到的是旧状态,因为reducer还没处理动作
  const users = store.getState().users;

  // 业务逻辑
  ....................................

  return next(action);
};

我理解createAsyncThunk本身是处理异步逻辑的中间件,Redux存在中间件链:
Action => middleware A => middleware B => middleware C => Reducer => Store

我想要在middleware B中访问middleware A(也就是createAsyncThunk)的执行结果,实现中间件之间的联动。在Redux里有没有办法做到?

补充细节

我用这个中间件通过Socket IO和Laravel Echo建立私有WebSocket连接,需要用到createAsyncThunk成功响应后返回的一个ID,用这个ID拼接私有频道名称:

echo.private(`transport.${id}`).listen(...);

解决方案

1. 直接监听fulfilled动作,从动作payload取数据

不需要依赖getState(),中间件可以直接判断当前动作是否是getUsers.fulfilled,然后从action.payload里拿到需要的ID——createAsyncThunk的fulfilled动作payload就是异步请求返回的数据,这比等reducer更新状态更直接可靠。

修改后的中间件示例:

const customMiddleware = store => next => action => {
  // 监听getUsers的fulfilled动作
  if (getUsers.fulfilled.match(action)) {
    // 从动作payload里直接提取需要的ID
    const targetId = action.payload.targetId; // 假设payload包含该ID
    // 建立WebSocket连接
    echo.private(`transport.${targetId}`).listen('SomeEvent', (e) => {
      // 处理WebSocket事件,可通过dispatch更新状态
      store.dispatch(someAction(e.data));
    });
  }

  return next(action);
};

2. 调整中间件执行顺序

Redux中间件的执行顺序由configureStore中传入的数组顺序决定:将自定义中间件放在thunk中间件之后,这样createAsyncThunk完成异步请求并发出fulfilled动作时,会先经过你的自定义中间件,再到达reducer。同样,这里依然推荐直接从action.payload取数据,而非依赖getState()的旧状态。

配置Store示例:

import { configureStore } from '@reduxjs/toolkit';
import thunk from 'redux-thunk';
import customMiddleware from './customMiddleware';
import usersReducer from './usersSlice';

export const store = configureStore({
  reducer: {
    users: usersReducer,
  },
  middleware: [thunk, customMiddleware], // 先执行thunk,再执行自定义中间件
});

3. 在createAsyncThunk内部直接处理WebSocket逻辑

如果WebSocket连接逻辑与该异步请求强绑定,完全可以把建立连接的代码放到createAsyncThunk的成功回调里,无需通过中间件:

export const getUsers = createAsyncThunk(
  'users/getUsers',
  async (arg, { rejectWithValue, dispatch }) => {
    try {
      const response = await axios.get('users');
      const { users, targetId } = response.data;
      // 直接建立WebSocket连接
      echo.private(`transport.${targetId}`).listen('SomeEvent', (e) => {
        dispatch(someAction(e.data));
      });
      return response.data;
    } catch (error) {
      return rejectWithValue(error.response.data);
    }
  },
);

这种方式更直接,避免了中间件的依赖问题,适合逻辑耦合度高的场景。


内容的提问来源于stack exchange,提问作者Nima Zarei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 15:51:41