Generator yield 语法使用,也叫生成器,实际上就是多个异步按顺序执行
function* gen(){ //第一步 开始 console.log("start"); var a = yield "aaa"; //第二步 console.log("---",a); //2 var x = yield 222; //第三步 console.log("---",x);//3 var y = yield 4; //第四步 console.log("---",y);//6 return "over" } var g = gen(); //任何东西都没有执行,返回的一个迭代器, 可以使用 for of 遍历 // next 的传值是上一段 yield 的返回值 console.log(g.next(1)); console.log(g.next(2)); console.log(g.next(3)); console.log(g.next(6));
可以看到,上面最后的调用,是可以封装成递归的,免得重复代码,多层嵌套,比如自己写一个,自运行的
const promisify = require("util").promisify; const fs = require("fs"); const readFile = promisify(fs.readFile); const path = require("path"); function resolve(p){ return path.resolve(__dirname,p); } function* gen(){ var data1 = yield readFile(resolve("./data/data1.json"),"utf-8"); console.log(data1); var data2 = yield readFile(resolve("./data/data2.json"),"utf-8"); console.log(data2); var num = yield 123456; console.log(num); } //简单版自运行co模块 function co(gen){ var g = gen(); //任何东西都没有执行,返回的一个迭代器 function next(res){ var result = g.next(res); if(!result.done){ Promise.resolve(result.value).then((res)=>{ next(res); }).catch((e)=>{ throw new Error(e); }) } } next(); } co(gen);
或者使用co模块
const fs = require('fs'); const co =require('co'); const readFile = function (fileName) { return new Promise(function (resolve, reject) { fs.readFile(fileName, "utf-8",function(error, data) { if (error) return reject(error); resolve(data); }); }); }; const gen = function* () { const f1 = yield readFile('./data1.txt'); const f2 = yield readFile('./data2.txt'); console.log(f1); console.log(f2); }; co(gen).then(function(data){ console.log(data); }).catch(function(ct){ console.log(ct); })
Yield * 表达式
如果在 Generator 函数内部,调用另一个 Generator 函数。需要在前者的函数体内部,自己手动完成遍历。
function* foo() { yield 'a'; yield 'b'; } function* bar() { yield 'x'; // 手动遍历 foo() for (let i of foo()) { console.log(i); } yield 'y'; } for (let v of bar()){ console.log(v); }
ES6 提供了yield*
表达式,作为解决办法,用来在一个 Generator 函数里面执行另一个 Generator 函数。
function* bar() { yield 'x'; yield* foo(); yield 'y'; }
flat 数组
var arr = [1, [[2, 3], 4], [5, 6]]; var flat = function* (a) { a.forEach(function (item) { if (typeof item !== 'number') { yield* flat(item); } else { yield item; } }); }; for (var f of flat(arr)){ console.log(f); }