关于dva的put,put.resolve
关于dva的put,put.resolve
? 由于项目使用的是dva.js,在项目重遇到一个场景是需要拿着特定的选中单据的taskId去获取单据真正的id,其中获取真正id的接口是需要轮询3次的,下面是项目中的一部分代码。
? 其中业务场景是这样的,在一个单据table选择页面,选择部分单据,然后点击创建出货资料按钮,调用接口createASNviaPoLines去获取到一个taskId,然后再带着这个taskId去轮询(轮询三次)获取单据的唯一id,获取成功之后才跳去到步骤条的第一步,否则返回首页
ui交互如下:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
/* eslint-disable no-unused-vars */
import { message } from 'antd'; import * as service from '@/service/createASN'; import { translateFormData } from '@/utils/fn'; export default { namespace: 'createASNSelectOrder', state: { }, reducers: { updateState(state, { payload }) { return { ...state, ...payload, }; }, }, effects: { // 轮询接口 *createTasks({ payload: { asnId } }, { put, call }) { console.log('id'); let { data } = yield call(service.createTasks, asnId); if (!data.success) { // 等待5秒 yield new Promise((resolve) => setTimeout(resolve, 5000)); let response = yield call(service.createTasks, asnId); if (!response.data.success) { // 等待5秒 yield new Promise((resolve) => setTimeout(resolve, 5000)); response = yield call(service.createTasks, asnId); if (!response.data.success) { message.error(response.data.failedReason); } } data = response.data; console.log(1111); yield put({ type: 'updateState', payload: { asnId: data.asnId, success: data.success } }); console.log(33333); } } // PO 根据可用POLines创建asn *createASNviaPOLines({ payload }, { put, call, select }) { console.log('start'); const { data: taskId } = yield call(service.createASNviaPoLines, payload); console.log('end', taskId); yield put.resolve({ type: 'createTasks', payload: { asnId: taskId } }); console.log('getid'); const { asnId, success } = yield select(({ createASNSelectOrder }) => createASNSelectOrder); console.log('getid--->跳转'); if (!asnId || !success) { yield put(routerRedux.goBack()); return false; } console.log('go'); yield put({ type: 'goCreateASNStep', payload: { asnId, OrderType: 'PO' } }); }, // 创建asn成功 跳转到步骤1,去补相关信息 *goCreateASNStep({ payload }, { put }) { console.log('好的---我跳转了'); const { asnId, OrderType } = payload; yield put(routerRedux.push(`/App/CreateASNStep/${OrderType}/${asnId}`)); }, }, }; |
打印结果如下:
? 其中用到了yield put(),yield put.resolve(),为了方便大家理解他们是否是阻塞的,下面用几个简单的例子来说明
案例代码如下:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
// xxx.jsx
textBtn = () => { const { dispatch } = this.props; dispatch({ type: 'asn/textbtn', payload: {}, }); } aynctextBtn = () => { const { dispatch } = this.props; dispatch({ type: 'asn/asynctextbtn', payload: {}, }); } <Button onClick={this.textBtn} type="primary">测试按钮</Button> <Button onClick={this.aynctextBtn} type="primary">异步测试按钮</Button> // xxx.js reducers: { initData(state, { payload }) { for (let i = 1; i < 10; i++) { console.log(i); } return { ...state, ...payload, }; }, }, effects: { //异步获取数据 *asyncinitData({ payload }, { put, call }) { yield put({ type: 'initData', }); }, // 点击按钮 *textbtn({ payload }, { put, call }) { console.log('开始测试'); yield put.resolve({ type: 'initData', payload: '我是一个测试语句', }); console.log('测试结束'); }, // 异步------点击按钮 *asynctextbtn({ payload }, { put, call }) { console.log('开始测试'); // yield put.resolve({ -------> 异步变同步,非组赛变阻塞 yield put({ type: 'asyncinitData', payload: '我是一个测试语句', }); // yield take('asyncinitData/@@end'); -------> 监听asyncinitData,等待asyncinitData执行完成在执行下面代码,非组赛变阻塞 console.log('测试结束'); }, } |
- 当点击测试按钮时候,控制台打印结果
- 当点击异步测试按钮时候,控制台打印结果
- 当点击异步测试按钮时候,但是把yield put改成yield put.resolve,控制台打印结果
- 当点击异步测试按钮时候,加上代码yield take('asyncinitData/@@end');,控制台打印结果
结论:
- yield put直接调用reducer,是堵塞的,同步,
- 调用非reducer函数,是非堵塞的,异步
- 使用put.resolve ,堵塞的,同步
- 使用yield take('asyncinitData/@@end')去监听asyncinitData执行
漫思