美文网首页
谈谈 generator

谈谈 generator

作者: MrAlexLee | 来源:发表于2019-12-28 00:28 被阅读0次

概念和基本操作

1,实质是一个状态机,在生成器里面可以包含多种状态,可以暂停。
2,执行generator函数会返回一个遍历器对象,可以一次遍历函数内部的每一个状态
3,通过关键字yield来定义状态,通过next()来遍历状态。
举个栗子:

        function* helloWorldGenerator(){  
            yield 'hello' ;  
            yield 'world' ;  
            return 'ending'  
        }  
        
        var hw = helloWorldGenerator();//这个定义一个遍历器对象  
        hw.next()//{ value:'hello' , done: false}  
        hw.next()//{ value:'world', done: false}  
        hw.next()//{ value:'ending' , done: true}  
        hw.next()//{ value:undefined , done: true}  
        

参数传递和状态遍历

注意的点:
1,next()参数传递。举个栗子:

        function* foo(x){  
            var y = 2 * (yield (x+1));  
            var z = yield (y/3);  
            return (x+y+z)  
        }  
        
        var a = foo(5);  
        a.next();//{value:6.done:false}  
        a.next();//{value:NaN.done:false}  
        a.next();//{value: NaN.done:true}  
        
        var b = foo(5);  
        b.next();//{value:6.done:false}  
        b.next(12);//{value:8.done:false}  
        b.next(13);//{value: 42.done:true}  
        

b.next()语句只返回 yield 后面表达式的值,即 5+1=6;b.next(12)这次的参数 12 才会变为 yield(x+1)的返回值,所以 y = 2*12=24;且要 执行第二条 yield 语句,打印出的 value 值是 24/3=8;此时 z没有被赋值,因为在等待 yield(y/3)的返回值,也就是下一次next 的参数,所以b.next(13),这里的 13 就是整体 yield(y/3) 语句的返回值,z=13,且执行最后一条返回语句,5+24+13=42

2,可以通过 for…of 来遍历 yield 后面的值,也就是可以拿到所有状态,但是最后的 return语句不会执行。 举个栗子

        function* foo(){  
             yield 1;  
             yield 2;  
             yield 3;  
             yield 4;  
             yield 5;  
               return 6  
        }  
        for(let v of foo()){  
            console.log(v);  
        }  
        1,2,3,4,5  

用途

1,异步操作的同步化表达

ajax 请求,当请求到数据后要在这个异步函数中执行逻辑,使用 generator 函数可以将这执行逻辑取出来放在 ajax 下面。实现异步操作的同步化表达。 举个栗子

            
            function* main(){  
                var result = yield request('' [http://some.url''](http://some.url'')) ; 
                var res = JSON.parse(result);  
                console.log(res.data);  
            }  
            
            function request(url){  
                makeAjaxCall(url, function(response){  
                    it.next(response);  
                })  
            }  
            
            var it =main();  
            it.next();  

代码分析:it.next()执行request('' http://some.url'') ; 执行 request 函数,得到结果 response,然后 next(response);将参数作为yield 语句的返回结果赋值给 res。这样就能打印出 res.data了。

2,控制流管理

实际运用中主要是为了解决ajax回调地狱,用 promise 函数的 then 也可以来解决,但是使用 generator 函数可以更直接的将依赖拆解开来。举个栗子:

            step1(function (value1){  
                step2(value1, function(value2){  
                    …  
                })  
            })  
            
            使用 promise  
            
            Promise.resolve(step1).then(step2).then(res=>{  
                …  
            })  
            
            使用 generator  
            
            function* longRunningTask(value1){  
                try{  
                    var value2 = yield step1(value1);  
                    var value3 = yield step1(value2);  
                }catch(e){  
                  
                }  
            }  

但是我们要创建一个函数来一次自动执行所有步骤:

            
            function schedule(task){  
                var taskObj = task.next(task.value);  
                if(!taskObj.done){  
                    task.value = taskObj.value  
                    schedule(task)  
                }  
            }  

相关文章

网友评论

      本文标题:谈谈 generator

      本文链接:https://www.haomeiwen.com/subject/dtvjoctx.html