前端学习(六十四) JavaScript-Generator(javaScript)

什么是Generator?

Generator(生成器)属于ES6规范,可以将Generator看作一个可以暂停和恢复执行的函数

示例:

            function* a(){
                let b=yield 'b'
                console.log(b);
                yield 'b';
                return 'c'
            }

Generator通过 function* 进行定义,yield关键字定义了Generator内部的不同状态。

Generator函数调用时不是立即返回结果,而是生成一个generator对象,可以通过对象来控制Generator的执行过程,例如

            function* a(){
                let b=yield 'a'
                console.log(b);
                yield 'b';
                return 'c'
            }
            let b=a();
            console.log(b.next());
            console.log(b.next('foo'));
            console.log(b.next());

Generator函数被执行时返回一个暂停的Generator对象,可以用这个对象空值执行的过程;

每次调用该对象的next方法可以恢复Generator执行,执行过程遇到yield关键字会暂停执行;

如果Genertor对象的next方法有掺水,yield会结构并返回该参数(并赋值给yield左侧变量);

因此,在Generator外部可以通过传入的next参数来随时调整Generator后续行为;

            function* c(){
                let d=yield 'e';
                console.log(d);
                if(d=== 'foo'){
                    console.log('if');
                    
                }
                else{
                    console.log("else");
                    
                }
            }
            let f=c();
            console.log(f.next());
            console.log(f.next('foo'));

Iterator接口的实现和应用

实际上Generator对象同时实现了Iterator接口与可迭代协议,Generator实现了Iterator中的,next,return,throw方法,同时和其他类似数组对象一样具有Symbol.iterator属性

因此,我们可以通过for of,扩展运算符来自动执行它,而不需要手动.next()来执行

另外,可以通过yield* 实现非线性迭代,可以在yield*后面加上另一个Generator方法或者其他任意可迭代对象

            function* all(){
                yield 'a1';
                yield 'a2';
            }
            function* bll(){
                yield 'b1';
                yield* all();
                yield 'b2';
                yield* [1,23,2];
            }
            for(let g of bll()){
                console.log(g);
            }

输出:b1,a1,a2,b2,1,23,2

协程

Generator实现了协程的思想,即控制权的主动让出和恢复

yield关键字能够主动暂停执行,并将执行权转交还给Generator的调用者,调用者调用next(),generator再从之前的位置恢复执行,这么做的优点有

  • 程序自身可以ikongzhi各个子程序的切换
  • 让异步操作看上去像同步操作

常见的生产者和消费者模式:生产者(producer)生产数据,消费者(consumer)处理数据

            function* produceGen(){
                while(true){
                    let data=produceData(); //生产数据
                    yield data;
                }
            }
            function* consumer(){
                let producer = produceGen();
                while(true){
                    data = producer.next().value
                    consume()   //处理数据
                }
            }
            consumer();

由于Generator函数不能自动执行,要实现文件顺序读取,还需要通过不断调用next方法分次执行Generator函数中的代码;

日常工作可以直接借助co库来接收一个Generator函数,自动执行完内部的逻辑

猜你喜欢

转载自blog.csdn.net/zy21131437/article/details/81459504