React Redux Saga场景下如何在第一个函数执行完成后调用第二个函数
问题原因
你遇到的报错本质是redux-saga 默认触发的 action 不会返回 Promise,因此无法直接链式调用.then()方法:
- 你通过props拿到的
fetchCode本质是 Redux 绑定的dispatch函数,调用后返回的是action对象本身,不是异步Promise实例 fetchCode本身是redux-saga的worker生成器函数,不是普通的async异步函数,执行后也不会返回Promise
解决方案
以下是两种常用的落地方案,可按需选择:
方案1:包装action为Promise,适配.then()调用逻辑
不需要大幅改动现有流程,只需要在action传参时增加回调、saga执行完成后触发回调即可:
- 调整组件调用逻辑,把
fetchCode的调用包装为Promise:
if (this.props.page_num < this.props.numPages) { // 包装为Promise实例,拿到resolve/reject回调 new Promise((resolve, reject) => { this.props.fetchCode({ params, isFiltered, isSearched, resolve, reject }); }).then(() => { this.props.setPageNumber(this.props.page_num + 1); }); }
- 调整saga的
fetchCode逻辑,执行完成后触发对应回调:
export function* fetchCode(action) { try { const response = yield call(Services.fetchCode, action.params); const { dtoList } = response.data.pagedList; const num_pages = response.data.pagedList.numPages; const total_records = response.data.pagedList.totalRecords; const page_number = response.data.pagedList.pageNumber; const postCodeSetsData = dtoList.map(() => ({})); yield put(ActionCreator.setCodes(dtoList, num_pages, total_records, postCodeData, page_number, action.isFiltered, action.isSearched)); // 执行成功触发resolve回调 action.resolve?.(); } catch (error) { sagaException(error); // 执行失败触发reject回调 action.reject?.(error); } }
方案2:把顺序执行逻辑移到saga内部(更符合redux-saga的设计理念)
不需要改动组件的dispatch逻辑,直接在saga内部按顺序执行异步请求和更新页码的操作,天然保证执行顺序:
export function* fetchCode(action) { try { const response = yield call(Services.fetchCode, action.params); const { dtoList } = response.data.pagedList; const num_pages = response.data.pagedList.numPages; const total_records = response.data.pagedList.totalRecords; const page_number = response.data.pagedList.pageNumber; const postCodeSetsData = dtoList.map(() => ({})); yield put(ActionCreator.setCodes(dtoList, num_pages, total_records, postCodeData, page_number, action.isFiltered, action.isSearched)); // 可直接从store获取状态做分页判断 const { page_num, numPages } = yield select(state => state.codeModule); if (page_num < numPages) { // 直接在saga内部触发更新页码的action,保证在接口请求、数据更新完成后执行 yield put(ActionCreator.setPageNumber(page_num + 1)); } } catch (error) { sagaException(error); } }
内容的提问来源于stack exchange,提问作者rudeTool
相关产品推荐
相关产品推荐

