关于
dva
的
put,put.resolve
dva
put,put.resolve
由于项目使用的是
dva.js
,在项目重遇到一个场景是需要拿着特定的选中单据的
taskId
去获取单据真正的
id
,其中获取真正
id
的接口是需要轮询3次的,下面是项目中的一部分代码。
其中业务场景是这样的,在一个单据
table
选择页面,选择部分单据,然后点击创建出货资料按钮,调用接口
detailLines
去获取到一个
taskId
,然后再带着这个
taskId
去轮询(轮询三次)获取单据的唯一
id
,获取成功之后才跳去到步骤条的第一步,否则返回首页
import { message } from 'antd';
import * as service from '@/service/createASN';
import { translateFormData } from '@/utils/fn';
export default {
namespace: 'order',
state: { },
reducers: {
updateState(state, { payload }) {
return {
...state,
...payload,
};
},
},
effects: {
// 轮询接口
*createTasks({ payload: { id } }, { put, call }) {
console.log('id');
let { data } = yield call(service.createTasks, id);
if (!data.success) {
// 等待5秒
yield new Promise((resolve) => setTimeout(resolve, 5000));
let response = yield call(service.createTasks, id);
if (!response.data.success) {
// 等待5秒
yield new Promise((resolve) => setTimeout(resolve, 5000));
response = yield call(service.createTasks, id);
if (!response.data.success) {
message.error(response.data.failedReason);
}
}
data = response.data;
console.log(1111);
yield put({ type: 'updateState', payload: { id: data.id, success: data.success } });
console.log(33333);
}
}
*detailLines({ payload }, { put, call, select }) {
console.log('start');
const { data: taskId } = yield call(service.detailLines, payload);
console.log('end', taskId);
yield put.resolve({ type: 'createTasks', payload: { id: taskId } });
console.log('getid');
const { id, success } = yield select(({ createASNSelectOrder }) => createASNSelectOrder);
console.log('getid--->跳转');
if (!id || !success) {
yield put(routerRedux.goBack());
return false;
}
console.log('go');
yield put({ type: 'goTo', payload: { id, OrderType: 'PO' } });
},
// 创建成功 跳转
*goTo({ payload }, { put }) {
console.log('好的---我跳转了');
const { id, OrderType } = payload;
yield put(routerRedux.push(`/app/detail/${OrderType}/${id}`));
},
},
};
打印结果如下:
其中用到了
yield put()
,
yield put.resolve()
,为了方便大家理解他们是否是阻塞的,下面用几个简单的例子来说明
案例代码如下:
// 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
执行
版权声明:本文为YMX2020原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。