在Redux-Saga的Promise then函数内派发Action的正确方式
解决Redux-Saga中在Promise回调内派发Action无效的问题
其实你碰到的这个问题,本质是没摸透Redux-Saga的核心逻辑——它的generator函数必须通过yield来接管异步流程,直接在then()里调用put()根本不在saga的执行上下文里,自然不会生效。最规范的做法是用saga提供的call effect来处理Promise,把整个异步流程纳入generator的控制中。
先说说你之前写法的问题
估计你之前的代码大概是这样的:
// 你的axios请求函数 const apiPost = (data) => axios.post('/api/your-endpoint', data); // 有问题的saga function* myPostSaga(action) { apiPost(action.payload) .then(res => { // 这里直接调用put完全没用,因为没通过yield交给saga处理 put({ type: 'POST_SUCCESS', data: res.data }); }) .catch(err => { put({ type: 'POST_FAIL', error: err }); }); }
这里的put()只是创建了一个action对象,但没有被saga中间件执行,相当于你只是创建了个对象扔在那,没人帮你派发给store。
正确的实现方式
用call effect来调用返回Promise的函数,再配合try/catch处理成功和失败,整个流程都用yield来控制,这样put()就能正常生效了:
import { call, put, takeLatest } from 'redux-saga/effects'; import axios from 'axios'; // 你的API请求函数不用改,还是返回Promise const apiPost = (data) => axios.post('/api/your-endpoint', data); // 修正后的处理saga function* handlePostRequest(action) { try { // 用call来调用Promise函数,saga会自动等待它resolve const response = yield call(apiPost, action.payload); // 成功后通过yield put派发action yield put({ type: 'POST_SUCCESS', payload: response.data }); } catch (error) { // 捕获Promise的reject,派发失败action yield put({ type: 'POST_FAILURE', payload: error.message }); } } // 监听触发这个saga的action export function* watchPostActions() { yield takeLatest('POST_REQUEST', handlePostRequest); }
为什么这样就能行?
calleffect会让saga中间件去执行你传入的Promise函数,等Promise完成后,把结果返回给generator函数,相当于帮你把异步操作同步化了。yield put(...)会把创建好的action交给saga中间件,由它负责派发给Redux store,这样就能正常更新状态了。try/catch完美替代了Promise的then/catch回调,让代码逻辑更连贯,也符合generator的写法习惯。
要是你真的有特殊情况必须保留then回调(非常不推荐,会打乱saga的流程控制),那得在回调里用put.resolve()并且通过yield调用,但这种写法会让代码变得混乱难维护,所以优先推荐上面的call + try/catch方案。
内容的提问来源于stack exchange,提问作者alphadogg
相关产品推荐
相关产品推荐

