• js es6深入应用系列(Generator)


    前言

    generotor 和 普通函数的不同在于function 的时候加了一个*,

    是的,我们看到es5的一个陌生关键字,yield,这个是不寻常的,为什么这么说呢?

    这个在c#中,很常见的一个关键字,下面就来解释一下js中的。

    正文

    function* gen() {
    	yield "1";
    	yield "2"
    }
    var iterator = gen();
    console.log(iterator);
    console.log(iterator.next());
    console.log(iterator.next());
    console.log(iterator.next());
    

    这个玩意儿如果运行的话,会返回一个Iterator实例, 然后再执行Iterator实例的next()方法, 那么这个函数才开始真正运行,
    并把yield后面的值包装成固定对象并返回,直到运行到函数结尾, 最后再返回undefined;

    我为什么这么说呢?改一下代码:

    function* gen() {
    	yield "1";
    	console.log('123');
    	yield "2";
    }
    var iterator = gen();
    console.log(iterator);
    console.log(iterator.next());
    console.log(iterator.next());
    console.log(iterator.next());
    

    这个可以看图说话我就不多说了。

    下面介绍一下其他的一些特性。

    yield*

    yield* 表达式用于委托给另一个generator 或可迭代对象。

    下面是委托为另一个:generator

    function* foo() {
    	yield 0;
    	yield 1;
    }
    function* bar() {
    	yield 'x';
    	yield* foo();
    	yield 'y';
    }
    for (let v of bar()) {
    	console.log(v);
    };
    

    实际上上面就说了可以委托为任何可迭代的对象。

    function* g3() {
      yield* [1, 2];
      yield* "34";
      yield* arguments;
    }
    var iterator = g3(5, 6);
    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: "4", done: false }
    console.log(iterator.next()); // { value: 5, done: false }
    console.log(iterator.next()); // { value: 6, done: false }
    console.log(iterator.next()); // { value: undefined, done: true }
    

    return

    The return() method returns the given value and finishes the generator.

    function* gen() { 
      yield 1;
      yield 2;
      yield 3;
    }
    const g = gen();
    g.next();        // { value: 1, done: false }
    g.return('foo'); // { value: "foo", done: true }
    g.next();        // { value: undefined, done: true }
    

    throw()

    The throw() method resumes the execution of a generator by throwing an error into it and returns an object with two properties done and value.

    function* gen() {
    	while (true) {
    		try {
    			yield 42;
    		} catch (e) {
    			console.log('Error caught!');
    		}
    	}
    }
    
    const g = gen();
    g.next();
    // { value: 42, done: false }
    g.throw(new Error('Something went wrong'));
    // "Error caught!"
    // { value: 42, done: false }
    

    next

    next 分为带参数和不带参数,不带参数的我就不说了,说下带参数的。

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

    惊喜不惊喜意外不意外?

    过程其实也很简单,比如说第二个传入了12。

    这个运行过程其实是从第一个yiled 开始运行的,也就是这个12会替换(x + 1)

    这样y就等于24了,然后yield (y / 3) 就是8了。

    后续也是这样。

    应用

    <script>
    	"use strict";
    	function* main() {
    		var result = yield request("http://www.filltext.com?rows=10&f={firstName}");
    		console.log(result);
    		//do 别的ajax请求;
    	}
    	function request(url) {
    		var r = new XMLHttpRequest();
    		r.open("GET", url, true);
    		r.onreadystatechange = function () {
    			if (r.readyState != 4 || r.status != 200) return;
    			var data = JSON.parse(r.responseText);
    			//数据成功返回以后, 代码就能够继续往下走了;
    			it.next(data);
    		};
    		r.send();
    	}
    	var it = main();
    	it.next();
    	console.log("执行到这儿啦");
    </script>
    

    我把打印放出来:

    其实上面可能存在疑惑的地方,那就是为什么console.log(result);会打印出it.next(data);中data的结果。

    其实非常简单,当var result = yield request("http://www.filltext.com?rows=10&f={firstName}");执行完毕的时候,因为没有next,然后就被阻塞了。

    那么更具上面next的特性。it.next(data)中的data会替换:yield request("http://www.filltext.com?rows=10&f={firstName}"),那么result的结果就是data。

    实现了我们async和await的效果。

  • 相关阅读:
    由wifi吞吐量问题联想到的分治思维
    总结----调试问题套路(经验)
    常用指令备忘录----持续更新
    【mark】OS是否使用svc方式分开系统空间和用户空间的优劣
    转载----五种开源协议(GPL,LGPL,BSD,MIT,Apache)
    rt-thread 动态装载实现、优化
    转:嵌入式: jffs2,yaffs2,logfs,ubifs文件系统性能分析
    gcc ld 链接器相关知识,调试指令(程序员的自我修养----链接、装载与库)
    HTML5与CSS3经典代码
    jquery mobile上传图片完整例子(包含ios图片横向问题处理和C#后台图片压缩)
  • 原文地址:https://www.cnblogs.com/aoximin/p/12896574.html
Copyright © 2020-2023  润新知