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.限制抽奖次数

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button id="btn">抽奖</button>
<input type="text" id="ipt">
<script>
let oBtn = document.getElementById('btn');
let oIpt = document.getElementById('ipt');
let start = gen(5);
let timmer = null;
oBtn.onclick = () => {
start.next();
};
function draw(count) {
clearInterval(timmer);
let num = Math.floor(Math.random() * 30);
let prize = 0; timmer = setInterval(()=>{
prize++;
if( num === prize){
clearInterval(timmer);
alert("还可以抽"+count+"次");
return;
}
oIpt.value = prize;
}, 100); } function* gen(count) {
while (count > 0){
count--;
yield draw(count);
}
}
</script>
</body>
</html>

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('文件读取完成')
});

视频教程地址:http://edu.nodeing.com/course/50

es6+最佳入门实践(10)的更多相关文章

  1. es6+最佳入门实践(12)

    12.class基础用法和继承 12.1.class基础语法 在es5中,面向对象我们通常写成这样 function Person(name,age) { this.name = name; this ...

  2. es6+最佳入门实践(8)

    8.Promise 8.1.什么是异步? 要理解异步,首先,从同步代码开始说 alert(1) alert(2) 像上面的代码,执行顺序是从上到下,先后弹出1和2,这种代码叫做同步代码 alert(0 ...

  3. es6+最佳入门实践(7)

    7.set和map数据结构 7.1.什么是set? Set就是集合,集合是由一组无序且唯一的项组成,在es6中新增了set这种数据结构,有点类似于数组,但是它的元素是唯一的,没有重复 let st = ...

  4. es6+最佳入门实践(1)

    1.let和const 1.1.let和块级作用域 在es5中,js的作用域分为全局作用域和局部作用域,通常是用函数来区分的,函数内部属于局部作用域,在es6中新增了块级作用域的概念,使用{}括起来的 ...

  5. es6+最佳入门实践(14)

    14.模版字符串 模版字符串(template string)是增强版的字符串,定义一个模版字符串需要用到反引号 let s = `这是一个模版字符串` console.log(s) 14.1.模版字 ...

  6. es6+最佳入门实践(13)

    13.模块化 13.1.什么是模块化 模块化是一种处理复杂系统分解为更好的可管理模块的方式.通俗的讲就是把一个复杂的功能拆分成多个小功能,并且以一种良好的机制管理起来,这样就可以认为是模块化.就像作家 ...

  7. es6+最佳入门实践(9)

    9.Iterator和for...of 9.1.Iterator是什么? Iterator又叫做迭代器,它是一种接口,为各种不同的数据结构提供统一的访问机制.这里说的接口可以形象的理解为USB接口,有 ...

  8. es6+最佳入门实践(6)

    6.Symbol用法 6.1.什么是Symbol? Symbol是es6中一种新增加的数据类型,它表示独一无二的值.es5中我们把数据类型分为基本数据类型(字符串.数字.布尔.undefined.nu ...

  9. es6+最佳入门实践(5)

    5.对象扩展 5.1.对象简写 在es5中,有这样一种写法 var name = "xiaoqiang"; var age = 12; var obj = { name : nam ...

随机推荐

  1. FIFO的使用场景

    (1) 数据的缓冲.如模型图所示,如果数据的写入速率高,但间隔大,且会有突发;读出速率小,但相对均匀.则通过设置相应深度的FIFO,可以起到数据暂存的功能,且能够使后续处理流程平滑,避免前级突发时,后 ...

  2. stm32--FatFs移植(SPIFlash)

    前言 硬件: 单片机:stm32f072CB,sram大小16k.(其他单片机只要sram>8k即可通用) SPIFlash:W25Q128FV,16Mbyte,单次擦除最小4k. 程序使用Ke ...

  3. leetcode笔记--2 reverse string

    my answer: 出错点:new_list[s] = list_s[u-1-s] 这样会出错, 重点:(1) map(str, s) 函数的使用,例:ls = [1,2,3]rs = map(st ...

  4. 预装win8的笔记本如何重装win7

    测试电脑联想T440. 开机按F1,然后Enter,进入Bios设置. 先关闭Secure Boot,然后设置为Legacy Boot. 之后才能设置U盘为第一启动盘. 进入老毛桃的PE系统,使用Di ...

  5. HDFS分布式集群

    一.HDFS伪分布式环境搭建 Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统.它和现有的分布式文件系统有很多共同点.但同时, ...

  6. annoy安装

    yum install gcc-c++ #linux下需安装c++编译器 sudo pip install annoy

  7. HDU 4588 Count The Carries(数学统计)

    Description One day, Implus gets interested in binary addition and binary carry. He will transfer al ...

  8. 编程练习:寻找发帖"水王"扩展问题一

    回顾 寻找发帖水王的问题总结起来就是在一个数组中某一个元素出现次数超过了数组长度的一半,那么可以很顺利的找到这个元素,实现见"编程练习:寻找发帖水王" 扩展 上面的问题中,强调了某 ...

  9. mysql与hive2.1.1安装和配置

    1.mysql安装 这个安装很简单,是在线安装,只需要按顺序执行一下几个命令就ok了. (1)sudo apt-get install mysql-server (2)sudo apt-get ins ...

  10. POI实现excel的数据验证

    目录 前言 难点1:合并单元格 代码实现策略: step 1: 合并单元格 step 2: 给单元格赋值 难点2:数据验证-下拉框 代码实现策略: step 1:设置需要进行数据验证的单元格范围和可供 ...