Generator(生成器) 进修明白与实践

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代码

<div id="ajax">初始数据</div>
<button onclick="getSomeList()">要求ajax数据</button>
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

    原文作者:Hewitt
    原文地址: https://segmentfault.com/a/1190000018794491
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞