10.Generator
10.1.Generator是什么?
Generator函数是ES6提供的一种异步编程解决方案。在它的内部封装了多个状态,因此,又可以理解为一种状态机,执行Generator函数后返回一个迭代器对象,使用这个迭代器对象可以遍历出Generator函数内部的状态
Generator函数和传统函数的不同点有:1 函数定义的时候,function关键字后面加“*”, 2 内部使用yield关键字定义内部状态
function* HelloGenerator() { yield "状态1"; yield "状态2"; yield "状态3"; yield "状态4";}let hg = HelloGenerator();console.log(hg.next()); //{value: "状态1", done: false}console.log(hg.next()); //{value: "状态2", done: false}console.log(hg.next()); //{value: "状态3", done: false}console.log(hg.next()); //{value: "状态4", done: false}console.log(hg.next()); //{value: undefined, done: true}
Generator函数被调用后,并不会立即执行完成,而是会在遇到yield关键字后暂停,返回的也不是函数的运行结果,而是一个执行内部状态的指针对象(Iterator对象)
注意1: next方法内可以传参数,这个参数的值作为上一次状态的返回值
function* HelloGenerator() { let result = yield "状态1"; console.log(result); yield "状态2"; yield "状态3"; yield "状态4";}let hg = HelloGenerator();console.log(hg.next());console.log(hg.next('nodeing'));
注意2: 可以使用for...of来遍历Generator内部状态
function* HelloGenerator() { yield "状态1"; yield "状态2"; yield "状态3"; yield "状态4";}let hg = HelloGenerator();for( let i of hg){ console.log(i);}
注意3: 对象没有Symbol.Iterator属性,我们可以手动添加,让其具有Iterator接口
let obj = {};function* gen() { yield 1; yield 2; yield 3; yield 4;}obj[Symbol.iterator] = gen;for(let a of obj){ console.log(a);}
10.2.Generator应用
1.限制抽奖次数
Title
2.异步读取文件
const fs = require('fs');function readFile(path) { return new Promise((resolve, reject) => { fs.readFile(path, (err, data) => { if(err){ reject(err) }else { resolve(data) } }) })}function* asyncFile() { yield readFile('a.txt'); yield readFile('b.txt'); yield readFile('c.txt');}let gen = asyncFile();gen.next().value.then((data)=>{ console.log(data.toString()); return gen.next().value;}).then((data2)=>{ console.log(data2.toString()); return gen.next().value;}).then((data3)=>{ console.log(data3.toString())});
如果觉得上面的写法还比较麻烦的话,我们可以引入一个co模块,让aysncFile里面的代码自动执行
const co = require('co');function* asyncFile() { let a = yield readFile('a.txt'); let b = yield readFile('b.txt'); let c = yield readFile('c.txt'); console.log(a.toString(), b.toString(), c.toString())}co(asyncFile()).then(()=>{ console.log('文件读取完成')});
视频教程地址: