dva model 中使用yield put 执行effects中另一个方法,发起请求,不会等这个请求执行完才执行下面的方法。
问题背景
问题描述
dva model 中使用yield put 执行effects中另一个方法,发起请求,不会等这个请求执行完才执行下面的方法。
effects: {
*effectAll({
payload }, {
put, call }) {
console.log('effectAll-start')
yield put({
type: 'effect1' });
yield put({
type: 'effect2' });
console.log('effectAll-end')
},
*effect1({
payload }, {
call }) {
yield call(serviceB, payload);
console.log('1111')
},
*effect2({
payload }, {
call }) {
yield call(serviceB, payload);
console.log('2222')
}
},
期望结果为
effectAll-start
1111
2222
effectAll-end
实际结果为
effectAll-start
effectAll-end
1111
2222
or
effectAll-start
effectAll-end
2222
1111
两种结果不同,哪个请求完成的快哪个在前面,非阻塞运行
问题解析
-
put是一个非阻塞的方法,put的使用效果和在外部使用dispatch是一样的;
-
如果我们想等待1执行完再接下去执行2,那就需要阻塞运行;
put(action): 创建一个 Effect 描述信息,用来命令 middleware 向 Store 发起一个 action。 这个 effect 是非阻塞型的,并且所有向下游抛出的错误(例如在 reducer 中),都不会冒泡回到 saga 当中。
问题解决过程
- 查看dva官方文档,没有发现相关内容
- 搜索’'dva effect调用effect"发现两种解决方案,均为使用redux-saga
阻塞运行的解决方案
使用put.slove
put.resolve(action):类似 put,但 effect 是阻塞型的(如果从 dispatch 返回了 promise,它将会等待其结果),并且会从下游冒泡错误。
effects: {
*effectAll({
payload }, {
put, call }) {
console.log('effectAll-start')
yield put.resolve({
type: 'effect1' });
yield put.resolve({
type: 'effect2' });
console.log('effectAll-end')
},
*effect1({
payload }, {
call }) {
yield call(serviceB, payload);
console.log('1111')
},
*effect2({
payload }, {
call }) {
yield call(serviceB, payload);
console.log('2222')
}
},
使用take
effects: {
*effectAll({
payload }, {
put, call, take }) {
console.log('effectAll-start')
yield put({
type: 'effect1' });
yield take('effect1/@@end') //直到监听到结束才继续执行
yield put.resolve({
type: 'effect2' });
yield take('effect2/@@end') //直到监听到结束才继续执行
console.log('effectAll-end')
},
*effect1({
payload }, {
call }) {
yield call(serviceB, payload);
console.log('1111')
},
*effect2({
payload }, {
call }) {
yield call(serviceB, payload);
console.log('2222')
}
},