• 欢迎大家分享资料!前往留言板评论即可!

yield与dva流程控制

合宙 模组资料网 7个月前 (05-15) 92次浏览 已收录 0个评论 扫描二维码
文章目录[隐藏]

yield与dva流程控制

dva.js

dva 首先是一个基于 reduxredux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-routerfetch,所以也可以理解为一个轻量级的应用框架。

yield

  • yield是ES6的新关键字,使生成器函数执行暂停,yield关键字后面的表达式的值返回给生成器的调用者。它可以被认为是一个基于生成器的版本的return关键字。
  • yield关键字实际返回一个IteratorResult(迭代器)对象,它有两个属性,value和done,分别代表返回值和是否完成。
  • yield无法单独工作,需要配合generator(生成器)的其他函数,如next,懒汉式操作,展现强大的主动控制特性。

迭代器(Iterator)和生成器(Generator)

迭代器:迭代器是一种特殊对象,它具有一些专门为迭代过程设计的专有接口,所有的迭代器对象都有一个next()方法,每次调用都返回一个结果对象。

下面用ES5的语法创建一个迭代器

// ES5迭代器
function createIterator(items) {
    var i = 0;
    return {
        next: function() {
            var done = (i >= items.length);
            var value = !done ? items[i++] : undefined;
            return {
                done: done,
                value: value
            };
        }
    };
}

生成器: 生成器是一种返回迭代器的函数,通过function关键字后的星号(*)来表示,函数中会用到新的关键字yield。

星号可以紧挨着function关键字,也可以在中间添加一个空格。

// 生成器
function *createIterator() {
    yield 1;
    yield 2;
    yield 3;
}
// 生成器能像正规函数那样被调用,但会返回一个迭代器
let iterator = createIterator();
console.log(iterator.next().value); // 1
console.log(iterator.next().value); // 2
console.log(iterator.next().value); // 3

在这个示例中,createlterator()前的星号表明它是一个生成器;yield关键字也是ES6的新特性,可以通过它来指定调用迭代器的next()方法时的返回值及返回顺序。生成迭代器后,连续3次调用它的next()方法返回3个不同的值,分别是1、2和3。生成器的调用过程与其他函数一样,最终返回的是创建好的迭代器。

// ES6迭代器
function *createIterator(items) {
    for (let i = 0; i < items.length; i++) {
        yield items[i];
    }
}
let iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: 3, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
// 之后的所有调用
console.log(iterator.next()); // "{ value: undefined, done: true }"

生成器函数最有趣的部分是,每当执行完一条yield语句后函数就会自动停止执行。

【使用限制】yield关键字只可在生成器内部使用,在其他地方使用会导致程序抛出错误

function *createIterator *(items) {
    items.forEach(function(item) {
        // 语法错误
        yield item + 1;
    });
}

从字面上看,yield关键字确实在createlterator()函数内部,但是它与return关键字一样,二者都不能穿透函数边界。嵌套函数中的return语句不能用作外部函数的返回语句,而此处嵌套函数中的yield语句会导致程序抛出语法错误。

也可以通过函数表达式来创建生成器,只需在function关键字和小括号中间添加一个星号(*)即可

可迭代对象

 可迭代对象具有Symbol.iterator属性,是一种与迭代器密切相关的对象。

​ Symbol.iterator通过指定的函数可以返回一个作用于附属对象的迭代器。在ES6中,所有的集合对象(数组、Set集合及Map集合)和字符串都是可迭代对象,这些对象中都有默认的迭代器。ES6中新加入的特性for-of循环需要用到可迭代对象的这些功能。

……

简单模拟dva处理effects函数

经过以上对于yield与迭代器的分析,我们可以以call为例模拟dva的处理流程。

  • 遍历model下的effects
  • 遍历effects下的函数
// 模拟业务流程
// models
function* requestCom() {
        let comRes = yield getCommit
        let repRes = yield getReply.bind(this, comRes.id)
        console.log(repRes);
    }
// 获取评论
const getCommit = () => {
        return { id: "1", value: "评论" }
    }
// 根据id获取评论下的回复
const getReply = (id) => {
    if (!id) return null
    return [
        { id: 101, content: "hahah" },
        { id: 102, content: "heheh" },
        { id: 103, content: "huhuh" },
        { id: 104, content: "xixix" },
    ]
}

// dva流程
let resCommIterator = requestCom()
    // TODO fn 类型判断、可迭代判断 ...
    // redux-saga.js
    // createPromiseMiddleware.js
let comValue = resCommIterator.next().value;
let repValue = resCommIterator.next(comValue()).value
let result = repValue()
console.log(comValue());
console.log(repValue());

业务代码中的写法

// models -- comment
* fetch_add_topic({}, { call, put, select }) {
            const commResponse = yield call(get_topic);
            if (ValidResponse(commResponse)) {
                let id = commResponse.data.id
                const replyResponse = yield call(get_reply, {id});
                if (ValidResponse(commResponse)) {
                  message.success("获取成功!")
                    yield put({
                        type: 'saveReply',
                        payload: { data: replyResponse.data, topic_id: payload.topic_id},
                    });   
                }
            }
        },


// services          
// 获取评论
export async function get_topic(params) {
    return request('/dev/site/topic', {
        method: 'GET',
        params,
    });
}

// 获取回复
export async function get_reply(params) {
    return request('/dev/site/reply', {
        method: 'GET',
        params,
    });
}

源码分析

dva/ createPromiseMiddleware.js

.umi/plugin-dva/dva.ts


转载请注明原文链接:yield与dva流程控制
喜欢 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址