从 generator 函数 到 redux -saga (一)

7 篇文章 0 订阅

Generator 函数是 ES6 提供的一种异步编程解决方案

教程可查看 阮老师所著es6  

用例1,对象转可执行的数组


var myIterable = {};
myIterable[Symbol.iterator] = function* () {
  yield 1;
  yield 2;
  yield 3;
};

console.log([...myIterable]);

2. 向generator 内部传值 ((1)

function* foo(x) {
  var y = 2 * (yield (x + 1));
  var z = yield (y / 3);
  return (x + y + z);
}

var a = foo(5);
a.next() // 6
a.next() //NaN
a.next() //NaN

var b = foo(5);
b.next() //6 
b.next(12) //8
b.next(13) //42

 向 generator 内部传值(2)

function* dataConsumer() {
  console.log('Started');
  console.log('start two');
  console.log(`1. ${ yield }`);
  console.log(`2. ${ yield }`);
  return 'result';
}

let genObj = dataConsumer();

genObj.next();
//Started
genObj.next('a')
//1. a
genObj.next('b')
//2. b

3,第一次调用传参 

function wrapper(generatorFunction) {
  return function (...args) {
    let generatorObject = generatorFunction(...args);
    generatorObject.next()
    return generatorObject;
  };
}

const wrapped = wrapper(function* () {
  console.log(`First input: ${yield}`);
  return 'DONE';
});

wrapped().next('hello!')

4,对比用 generator 函数和普通函数 生成斐波那契数列

function* gennerator(){
	let [ prev, curr ] = [ 0, 1 ];
	for(;;){
		yield curr;
		[ prev,curr] = [curr,curr+prev];
	}
}

for(let n of gennerator()){
	if(n<1000){
		console.log(n);
	}
}
const fibonacci = (function(){
	let cache = [];
	return function(number){
		if(typeof cache[number]!=="undefined"){
			return cache[number]
		}
		return cache[number]=(number==1||number==0)?number:fibonacci(number-2)+fibonacci(number-1);
	}
})()
console.log(fibonacci(100));

5,给对象部署iterator 接口

function* objectEntries() {
  let propKeys = Object.keys(this);
  
  for (let propKey of propKeys) {
    yield [propKey, this[propKey]];
  }
}
  let jane = { first: 'Jane', last: 'Doe' };
  
  jane[Symbol.iterator] = objectEntries;
  
  for (let [key, value] of jane) {
	console.log(`${key}: ${value}`);
  }

6 ,Generator.prototype.throw()

Generator 函数返回的遍历器对象,都有一个throw方法,可以在函数体外抛出错误,然后在 Generator 函数体内捕获。

注:内部的catch 语句只能执行一次错误 第二次错误 会被外部的catch 语句捕获

var g = function* () {
	try {
	  yield;
	} catch (e) {
	  console.log('内部捕获', e);
	}
  };
  
  var i = g();
  i.next();
  
  try {
	i.throw('a');
	i.throw('b');
  } catch (e) {
	console.log('外部捕获', e);
  }

7.  Generator.prototype.return()

Generator 函数返回的遍历器对象,还有一个return方法,可以返回给定的值,并且终结遍历 Generator 函数。

function* gen() {
	yield 1;
	yield 2;
	yield 3;
  }
let g = gen();

console.log(g.next());  //{value: 1, done: false}
console.log(g.return("response")); //{value: "response", done: true}
console.log(g.next()); //{value: undefined, done: true}

 如果 Generator 函数内部有try...finally代码块,且正在执行try代码块,那么return方法会推迟到finally代码块执行完再执行。

function* numbers () {
	yield 1;
	try {
	  yield 2;
	  yield 3;
	} finally {
	  yield 4;
	  yield 5;
	}
	yield 6;
  }
  var g = numbers();
  g.next() // { value: 1, done: false }
  g.next() // { value: 2, done: false }
  g.return(7) // { value: 4, done: false }
  g.next() // { value: 5, done: false }
  g.next() // { value: 7, done: true }

8, yield* 表达式

如果在 Generator 函数内部,调用另一个 Generator 函数,默认情况下是没有效果的。

function* foo(){
	yield 'a';
	yield 'b';
}
function* bar(){
	yield "x";
	foo();
	yield "y";
}

for (let v of bar()){
	console.log(v);
}

 这个就需要用到yield*表达式,用来在一个 Generator 函数里面执行另一个 Generator 函数。

function* bar() {
  yield 'x';
  yield* foo();
  yield 'y';
}

// 等同于
function* bar() {
  yield 'x';
  yield 'a';
  yield 'b';
  yield 'y';
}

// 等同于
function* bar() {
  yield 'x';
  for (let v of foo()) {
    yield v;
  }
  yield 'y';
}

for (let v of bar()){
  console.log(v);
}
// "x"
// "a"
// "b"
// "y"

如果yield*后面跟着一个数组,由于数组原生支持遍历器,因此就会遍历数组成员。

function* gen(){
  yield* ["a", "b", "c"];
}

gen().next() // { value:"a", done:false }

实际上,任何数据结构只要有 Iterator 接口,就可以被yield*遍历。

let read = (function* () {
  yield 'hello';
  yield* 'hello';
})();

read.next().value // "hello"
read.next().value // "h"

yield*命令可以很方便地取出嵌套数组的所有成员。

function* iterTree(tree) {
  if (Array.isArray(tree)) {
    for(let i=0; i < tree.length; i++) {
      yield* iterTree(tree[i]);
    }
  } else {
    yield tree;
  }
}

const tree = [ 'a', ['b', 'c'], ['d', 'e'] ];

for(let x of iterTree(tree)) {
  console.log(x);
}
// a

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值