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

Redux Toolkit中thunk中间件如何返回Promise实现异步后跳转

问题根源
  • thunk内部catch块直接return错误对象,相当于把所有请求异常内部消化,thunk永远不会进入rejected状态,外层拿不到错误
  • 调用dispatch(addExpense(form))后没有等待异步逻辑执行完就直接跑路由跳转代码,自然会出现请求未完成就跳页的情况
  • Redux Toolkit的createAsyncThunk默认dispatch后返回的Promise不会抛出rejected错误,需要手动调用unwrap拆包才能正常捕获异常
具体修改步骤

1. 修正thunk定义,不要吞掉错误

用createAsyncThunk自带的rejectWithValue工具处理错误返回,不要自己在catch里返回混合成功/失败的结构:

import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "../../../../src/axios";

export const addExpense = createAsyncThunk(
    "expense/addExpense",
    async (expense, { rejectWithValue }) => {
        try {
            const res = await axios.post("/expense", expense);
            return res.data.expense;
        } catch (err) {
            // 把后端返回的错误信息传到rejected action中
            return rejectWithValue(err.response.data.message);
        }
    }
);

2. 同步修改extraReducers状态逻辑

适配新的thunk返回结构,每次发请求前清空旧错误:

[addExpense.pending]: (state) => {
    state.creatingExpense = true;
    state.error = null;
},
[addExpense.fulfilled]: (state, action) => {
    const expense = action.payload;
    state.creatingExpense = false;
    if (state.expense && state.currentMonth === expense.month) {
        state.expense = [...state.expense, expense];
    }
},
[addExpense.rejected]: (state, action) => {
    state.creatingExpense = false;
    state.error = action.payload || action.error.message;
},

3. 修改提交逻辑,等待请求完成再跳转

调用unwrap()拆包Promise,请求成功后再执行路由跳转,失败时进catch分支处理错误:

const handleSubmit = async (e) => {
    e.preventDefault();
    const year = form.date.split("-")[0];
    const month = form.date.split("-")[1];
    try {
        // 等待异步请求完成
        await dispatch(addExpense(form)).unwrap();
        // 只有请求成功才会走到这里执行跳转
        navigate(`/year/${year}/${months[month - 1]}`);
    } catch (err) {
        // 请求失败会进入这里,可自由处理错误
        console.log(err);
        alert(err);
    }
};

关键提示:如果不用async/await,用链式调用写法也可以,只要记得加.unwrap()就行,示例:

dispatch(addExpense(form))
.unwrap()
.then(() => {
    navigate(`/year/${year}/${months[month - 1]}`);
})
.catch((err) => {
    console.log(err);
});

内容的提问来源于stack exchange,提问作者Deep Shah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 19:15:34