关于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('测试结束');
        },
 }
  1. 当点击测试按钮时候,控制台打印结果
    在这里插入图片描述
  2. 当点击异步测试按钮时候,控制台打印结果
    在这里插入图片描述
  3. 当点击异步测试按钮时候,但是把yield put改成yield put.resolve,控制台打印结果
    在这里插入图片描述
  4. 当点击异步测试按钮时候,加上代码yield take('asyncinitData/@@end');,控制台打印结果
    在这里插入图片描述

结论:

    • yield put直接调用reducer,是堵塞的,同步,
    • 调用非reducer函数,是非堵塞的,异步
    • 使用put.resolve ,堵塞的,同步
    • 使用yield take('asyncinitData/@@end')去监听asyncinitData执行

posted on 2022-01-24 17:58  漫思  阅读(360)  评论(0编辑  收藏  举报

导航