资讯专栏INFORMATION COLUMN

Generator(生成器) 学习理解与实践

Travis / 577人阅读

摘要:总结异步编程解决方案可理解为一种状态机,封装了多个内部状态可返回一个指向内部状态的指针对象遍历器对象,所以可理解为其是一个遍历器对象生成函数产出定义不同的内部状态,后跟表达式。

created at 2019-04-08
总结

异步编程解决方案

可理解为一种状态机,封装了多个内部状态

可返回一个指向内部状态的指针对象(遍历器对象Interator),所以可理解为其是一个遍历器对象生成函数

yield(产出),定义不同的内部状态,yield后跟表达式。

yield 表达式只能放在Generator函数中

(yield 表达式) 整个没有返回值,next()的参数可以被认为是上一个yield的返回值。

V8引擎直接忽略第一次next()的参数,因为没有上一次yield

调用next方法,是指针从函数头部或上一次停止的地方开始执行,直到遇到下一个yield表达式或return

当next的返回值的value属性为yield后表达式的结果或return后的值,done属性为true时表示遍历yield结束

对象中使用const obj = { myGeneratorMethod(){} } 等同于 obj = { myGeneratorMethod:function (){} }

yield* 用于在一个generator函数中执行另一个generator函数,并且会将另一个的yield全部执行完毕才会继续执行当前generator中的yield

基础语法
 function* generatorTest() {
    console.log("第一个yield之前的语句");
    yield "yield 1"
    yield "yield 3: 在表达式中要加括号" + (yield "yield 2: in expression")
    console.log("yield 之后 return之前");
    return "return"
}

const gt = generatorTest()
console.log(gt);
// 遍历器对象

/*
* 第一次调用是从函数头部开始执行,如果没有yield,也需要执行一次next才会执行这些语句
*/
console.log(gt.next());
// 第一个yield之前的语句
// {value: "yield 1", done: false}

console.log(gt.next());
// {value: "yield 2: in expression", done: false}

console.log(gt.next());
// {value: "yield 3: 在表达式中要加括号undefined", done: false}
// 上面出现undefined的原因是next没有加参数

console.log(gt.next());
// yield 之后 return之前
// {value: "return", done: true}

console.log(gt.next());
// {value: "undefined", done: true}
实现斐波拉契数列

链接

给原生对象添加Iterator

先展示for of 对generator的作用

function* generatorForOf(){
    yield 1;
    yield 2;
    return 3;
}
/*
* for of 可以遍历Generator生成的Iterator对象
* 这里不能再遍历 gt 因为它已执行完毕
* 不会遍历return的值
*/
for (let item of generatorForOf()) {
    console.log("for of :", item);
}

给原生对象添加iterator, 让其可以被for of 遍历

function* objectAddIterator(obj) {
    const props = Reflect.ownKeys(obj)

    for (const key of props) {
        yield [key, obj[key]]
    }
}

const nativeObj = {
    a: 12,
    b: 34,
    [Symbol("symbol c")]: 3
}

for (const [key, value] of objectAddIterator(nativeObj)) {
    console.log(typeof key === "symbol" ? key.description : key, value);
}
应用场景 异步ajax请求

代码中的loading函数代码行数较多,也并非关键代码,所以不作展示。查看loading代码

初始数据
function requestData(callback) {
    function ajaxFn() {
        setTimeout(() => {
            ar.next("ajax返回结果")
        }, 2000);
    }

    function* asyncReqData() {
        loading(true)
        const result = yield ajaxFn()
        callback(result)
        loading(false)
    }

    const ar = asyncReqData()
    ar.next()
}

function getSomeList() {
    requestData((res) => {
        document.getElementById("ajax").innerHTML = res
    })
}
控制同步操作的流程
function controlFlow() {
    const child1 = [() => {console.log("--",1); return "return 1"}, () => {console.log("--",2); return "return 2"}]
    const child2 = [() => {console.log("--",3); return "return 3"}, () => {console.log("--",4); return "return 4"}]
    function* generatorControl(child) {
        console.log("===========");
        for (let i = 0; i < child.length; i++) {
            yield child[i]()
        }
    }
    let parent = [{c: child1}, {c: child2}];

    function* parentFn(p){
        for (let i=0; i< p.length; i++){
            yield* generatorControl(p[i].c);
        }
    }

    for (let step of parentFn(parent)) {
        console.log(step);
    }
}

controlFlow()

本文包括对generate基础的学习与练习,与一些心得!【会持续学习,更新】

详细学习请移步下方参考链接

参考:

参考文章

欢迎交流 Github

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/103321.html

相关文章

  • co源码分析及其实践

    摘要:返回的结果是一个对象,类似于表示本次后面执行之后返回的结果。对象用于一个异步操作的最终完成或失败及其结果值的表示简单点说就是处理异步请求。源码分析主要脉络函数调用后,返回一个实例。参考链接解释对象的用法的源码及其用法 本文始发于我的个人博客,如需转载请注明出处。为了更好的阅读体验,可以直接进去我的个人博客看。 前言 知识储备 阅读本文需要对Generator和Promise有一个基本的...

    vincent_xyb 评论0 收藏0
  • 生成式对抗网络(GAN)如何快速理解

    摘要:目前,生成对抗网络的大部分应用都是在计算机视觉领域。生成对抗网络生成对抗网络框架是由等人于年设计的生成模型。在设置中,两个由神经网络进行表示的可微函数被锁定在一个游戏中。我们提出了深度卷积生成对抗网络的实现。 让我们假设这样一种情景:你的邻居正在举办一场非常酷的聚会,你非常想去参加。但有要参加聚会的话,你需要一张特价票,而这个票早就已经卖完了。而对于这次聚会的组织者来说,为了让聚会能够成功举...

    Leo_chen 评论0 收藏0
  • 从零组装新工具 - Koa2

    摘要:返回后,代表操作已完成,记录结束时间并输出。从零组装因为对的学习和使用,知道了自己对于后台框架的真实需求。所以这回决定不用之内的工具,而是自己从零开始,组装一个适合自己的框架。就是去和上,寻找一个一个的包并组装在一起了而已。 起因 作为一个前端,Node.js算是必备知识之一。同时因为自己需要做一些后台性的工作,或者完成一个小型应用。所以学习了Node的Express框架,用于辅助和加...

    sutaking 评论0 收藏0
  • JavaScript 异步

    摘要:从最开始的到封装后的都在试图解决异步编程过程中的问题。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。写一个符合规范并可配合使用的写一个符合规范并可配合使用的理解的工作原理采用回调函数来处理异步编程。 JavaScript怎么使用循环代替(异步)递归 问题描述 在开发过程中,遇到一个需求:在系统初始化时通过http获取一个第三方服务器端的列表,第三方服务器提供了一个接口,可通过...

    tuniutech 评论0 收藏0
  • ES6学习笔记之Generator函数

    摘要:调用函数后和普通函数不同的是,该函数并不立即执行,也不返回函数执行结果,而是返回一个指向内部状态的对象,也可以看作是一个遍历器对象。第一个只是用来启动函数内部的遍历器,传参也没有多大意义。 之前断断续续接触到了一些ES6的知识,异步编程方面听得比较多的就是Promise,直到最近比较系统地学习了ES6的新特性才发现Generator这个神奇的存在,它可以实现一些前所未有的事情,让我顿时...

    cjie 评论0 收藏0

发表评论

0条评论

Travis

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<