当前位置: 代码迷 >> 综合 >> 从 generator 函数 到 redux -saga (一)
  详细解决方案

从 generator 函数 到 redux -saga (一)

热度:35   发布时间:2023-11-21 05:20:55.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() //NaNvar 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

 

  相关解决方案