[ES6系列-07]Generator Function: 生成器函数
【原创】码路工人 Coder-Power
大家好,这里是码路工人有力量,我是码路工人,你们是力量。
Generator function 生成器函数是ES6中新增的语法糖,本质上讲,就是以封装成一个遍历器的形式,让编码的你获得程序的执行控制权,通俗地说就是,流程控制上,踹一脚,走一步,不要太暴力~
0.前言
要说到生成器函数,就不得不提到javascript的异步编程方式演进史。
(不能跑题不能跑题不能跑题)
- 1.普通的回调函数方式(callback)
- 2.事件/发布--订阅者模式(event/publisher--observer)
- 3.Promise
- 4.Generator
- 5.async/await(在ES8/ES2017中正式提出)
其中Promise是一个里程碑,解决了回调函数嵌套时的callback hell回调地狱问题(层级嵌套太多难以阅读与维护)。
而本文主角Generator更像是作为一个过渡语法,在推出async/await后就基本很少用了。
async/await,CSharper转前端,一看就像见到亲人,C#中有同样的语法。(#注:C# 5.0 中加入的)
话说语法演化地真是方便啊。在后面的文章中将单独给Promise和async/await开贴。
1.一句话介绍你自己
1.1 Talk is cheep, show you the CODE!
/* eg.0
* Simple Example of Generator-Function
*/
//----------------------------------------
let songs = ["Hero", "Here I am", "The Show"]
// Generator-Function is Here Below:
function *play(songs) {
for(let i=0; i<songs.length; i++) {
yield songs[i]
}
// 这里可以有return
}
let g = play(songs)
let next = g.next()
console.log(next) // { value: 'Hero', done: false }
next = g.next()
console.log(next) // { value: 'Here I am', done: false }
next = g.next()
console.log(next) // { value: 'The Show', done: false }
next = g.next()
console.log(next) // { value: undefined, done: true }
//----------------------------------------
1.2 关于生成器函数的定义
第一,函数定义处有个
*符号。*既可以紧跟在function后面,也可以贴在函数名前。第二,函数内有
yield关键字用以中断处理流程,并可以临时对外提供一个返回值。
其它,写法上与普通函数无异
1.3 关于生成器函数的使用
1.像普通函数一样调用,得到的不是任何具体的返回值,而是一个迭代器。(也可以看作是一个状态机)
2.来一脚试试。通过调用得到的迭代器对象上的
next()方法,开始得到第一个返回值对象。3.一直踹。每一次调用
next()方法,得到一个结果对象,可以看到上面代码注释中的打印信息。其中
value即当前获得的值,done即迭代状态,它只有ture/false两种可能,当它变为true,即迭代完成。
2.主流使用方式
正常的使用方式也即良好的实践吧,应该是配合promise来使用的。
来一个简陋的示例:
/* eg.1
* Simple Example of Generator-Function
*/
//----------------------------------------
function* func() {
// 这里应该是ajax请求,结果是一个promise对象,简单模拟一下
yield new Promise(function(resolve,reject){
resolve('Hello')
})
// 这里应该是ajax请求,结果是一个promise对象,简单模拟一下
yield new Promise(function(resolve,reject){
resolve('World')
})
}
let g = func()
g.next().value.then((data) => {
console.log('log-1:', data)
return g.next().value
}).then((data) => {
console.log('log-2:', data)
})
// log-1: Hello
// log-2: World
//----------------------------------------
这样,就将异步的ajax处理简单地以同步的样子书写出来了。
3.粗陋的实践
除了可以处理异步,码路工人个人觉得,Generator比较适合用在循环处理的场景。其中就实践过类似下面这个处理的例子:
/* eg.2 (part1)
* My Example of Generator-Function
*/
//----------------------------------------
// 以下代码中都省略掉了检测处理
// 首先来一个Gernerator函数
function *getDateInPeriod(from, to, includEnd=false) {
let fromDate = new Date(from)
let toDate = new Date(to)
if(includEnd) {
toDate = addDays(toDate, 1)
}
for(let date = fromDate;date < toDate; date=addDays(date, 1)) {
yield date
}
}
// 上面调用到了工具函数addDays
function addDays(date, days){
date = new Date(date.setDate(date.getDate() + days))
return date
}
//----------------------------------------
然后就是使用了,在循环取值的过程中,会有一些业务处理(同步的或异步的)。
/* eg.2 (part2)
* My Example of Generator-Function
*/
//----------------------------------------
let arrDate = getDateInPeriod('2019-06-06', '2019-06-30', true)
let daysInPeriod = arrDate.next()
while(!daysInPeriod.done) {
// 这里是一堆其它业务处理
console.log(daysInperiod)
daysInPeriod = arrDate.next()
}
console.log(daysInperiod)
//----------------------------------------
打印信息结果:
{ value: 2019-06-06T00:00:00.000Z, done: false }
{ value: 2019-06-07T00:00:00.000Z, done: false }
...
{ value: 2019-06-29T00:00:00.000Z, done: false }
{ value: 2019-06-30T00:00:00.000Z, done: false }
{ value: undefined, done: true }
上面的例子中,还是同步的方式。也许不是好的用法,但它能告诉你这是一种用法。
4.听说过的实践
这个码工没有实践过,大意是,Generator函数这个语法糖是按照yield将代码分成多个部分,人手工控制执行每一部分,于是,封装一个执行器函数,简化流程控制,使异步编程轻松愉快。
其实,在有了async/await后真的没有这个必要了。
(co.js就是一个这种Generator的执行库)
4.其它
除了上面介绍的生成器函数的主要用法,其实还有点其它小特性,码路工人并没有实践过,感觉也不怎么会用到,这里稍作了解即可。
4.1 可以接收由next传递进的参数。
/* eg.3
* parameters
*/
//----------------------------------------
function *genFunc(p) {
console.log(`p is ${p}`)
let p1 = yield p
console.log(`p1 is ${p1}`)
let p2 = yield p1
console.log(`p2 is ${p2}`)
}
let gen = genFunc(1)
// 第一次next无法传参到Generator函数,应该由最初的函数调用处传递
gen.next(2)
// 从第二步next() 传的参数,在第一个yield处接收
gen.next(3)
关于给yield传参确实看起来稍微有一点诡异,其实理解了也就不觉得奇怪了。
说明已贴在上面的注释中。
4.2 可以有默认的迭代器了
/* eg.4
* get value by for-of loop
*/
//----------------------------------------
function *foo() {
for(let i=0; i<6; i++) {
yield i
}
}
let gen = foo()
for(let item of gen) {
console.log(item)
}
// 打印结果:
// 0
// 1
// 2
// 3
// 4
// 5
//----------------------------------------
总结
关于生成器函数Generator Function就介绍到这里吧,
这要知道有这个语法糖就可以了,反正以后还真不一定用得到
异步处理主要用到的还是Promise跟async/await。
以上。
希望对你能有帮助,下期再见。
-END-
[ES6系列-07]Generator Function: 生成器函数的更多相关文章
- [js高手之路] es6系列教程 - 迭代器与生成器详解
什么是迭代器? 迭代器是一种特殊对象,这种对象具有以下特点: 1,所有对象都有一个next方法 2,每次调用next方法,都会返回一个对象,该对象包含两个属性,一个是value, 表示下一个将要返回的 ...
- [ES6系列-02]Arrow Function:Whats this?(箭头函数及它的this及其它)
[原创] 码路工人 大家好,这里是码路工人有力量,我是码路工人,你们是力量. 如果没用过CSharp的lambda 表达式,也没有了解过ES6,那第一眼看到这样代码什么感觉? /* eg.0 * fu ...
- Nodejs与ES6系列3:generator对象
3.generator对象 Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同.Generator的中文翻译是生成器,它是ECMAScript6(代号harmory) ...
- Generator - Python 生成器
Generator, python 生成器, 先熟悉一下儿相关定义, generator function 生成器函数, 生成器函数是一个在定义体中存有 'yield' 关键字的函数. 当生成器函数被 ...
- [js高手之路] es6系列教程 - 迭代器,生成器,for...of,entries,values,keys等详解
接着上文[js高手之路] es6系列教程 - 迭代器与生成器详解继续. 在es6中引入了一个新的循环结构for ....of, 主要是用来循环可迭代的对象,那么什么是可迭代的对象呢? 可迭代的对象一般 ...
- Python系列之 迭代器和生成器
很多Python的程序员都会混淆 迭代器 和 生成器 的概念和作用,分不清到底两个有什么区别.今天我们来好好说一说这两个概念. 迭代器(Iterator) Iterator Pattern Itera ...
- ES6新特性之生成器函数 (generator function): function*
一.什么是生成器函数(generator function)? 生成器函数是ES6的新特性之一,它是一个在执行时能中途暂时退出,后面重新调用又能重新进入继续执行的一种函数. 并且在函数内定义的变量的所 ...
- ES6笔记(5)-- Generator生成器函数
系列文章 -- ES6笔记系列 接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术. 在异步编程中,还 ...
- ES6生成器函数generator
ES6生成器函数generator generator是ES6新增的一个特殊函数,通过 function* 声明,函数体内通过 yield 来指明函数的暂停点,该函数返回一个迭代器,并且函数执行到 y ...
随机推荐
- java socket实现服务端,客户端简单网络通信。Chat
之前写的实现简单网络通信的代码,有一些严重bug.后面详细写. 根据上次的代码,主要增加了用户注册,登录页面,以及实现了实时显示当前在登录状态的人数.并解决一些上次未发现的bug.(主要功能代码参见之 ...
- python(while 循环语句)
一.循环语句 1.while 循环 当我们在 python 中需要重复执行一些动作的时候,这时我们就要用到循环 while 循环的结构,当条件成立的时候,就会执行里面的代码 while 循环不断的运行 ...
- Python编程求解第1天1分钱之后每天两倍持续一个月的等比数列问题
一.问题 问题1 场景:如果你未来的丈母娘要求你,第1天给她1分钱,第2天给2分钱,第3天给4分钱,以此类推,每天给前一天的2倍,给1个月(按30天)算就行.问:第30天给多少钱,总共给多少钱? 问题 ...
- NetCore项目实战篇03---HTTP Patch 更新数据
一.什么是HTPP Patch HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法. HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 ...
- PLAI那些事_06 FAE
没有了with表达,with,exp,body的id换成exp的lambda函数,从而可以没有with来进行实现.即,{with {id exp} body}换成了{{fun {id} body} e ...
- IoTClientTool自动升级更新
IoTClientTool是什么 IoTClientTool是什么,IoTClientTool是IoTClient开源组件的可视化操的作实现.方便对plc设备和ModBusRtu.BACnet.串口等 ...
- 软件——IDEA中如何去掉警告虚线
初次安装使用IDEA,总是能看到导入代码后,出现很多的波浪线,下划线和虚线,这是IDEA给我们的一些提示和警告,但是有时候我们并不需要,反而会让人看着很不爽,这里简单记录一下自己的调整方法,供其他的小 ...
- Minimum Euler Cycle(找规律+模拟)
\(给你一个nnn个结点的完全有向图,求其字典序最小的欧拉回路,输出lll到rrr之间的结点为多少.\) 模拟一下n=5的时候 开始肯定是1-2-1-3-1-4-1-5 注意这个时候不能再从5到1,否 ...
- Educational Codeforces Round 77 (Rated for Div. 2) C. Infinite Fence
C. Infinite Fence 题目大意:给板子涂色,首先板子是顺序的,然后可以涂两种颜色,如果是r的倍数涂成红色,是b的倍数涂成蓝色, 连续的k个相同的颜色则不能完成任务,能完成任务则输出OBE ...
- react中this.setState的理解
this.setState作用? 在react中要修改this.state要使用this.setState,因为this.state只是一个对象,单纯的修改state并不会触发ui更新.所以我们需要用 ...