【原创】码路工人 Coder-Power

大家好,这里是码路工人有力量,我是码路工人,你们是力量。

github-pages

博客园cnblogs


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 中加入的)

话说语法演化地真是方便啊。在后面的文章中将单独给Promiseasync/await开贴。

1.一句话介绍你自己

1.1 Talk is cheep, show you the CODE!

  1. /* eg.0
  2. * Simple Example of Generator-Function
  3. */
  4. //----------------------------------------
  5. let songs = ["Hero", "Here I am", "The Show"]
  6. // Generator-Function is Here Below:
  7. function *play(songs) {
  8. for(let i=0; i<songs.length; i++) {
  9. yield songs[i]
  10. }
  11. // 这里可以有return
  12. }
  13. let g = play(songs)
  14. let next = g.next()
  15. console.log(next) // { value: 'Hero', done: false }
  16. next = g.next()
  17. console.log(next) // { value: 'Here I am', done: false }
  18. next = g.next()
  19. console.log(next) // { value: 'The Show', done: false }
  20. next = g.next()
  21. console.log(next) // { value: undefined, done: true }
  22. //----------------------------------------

1.2 关于生成器函数的定义

  • 第一,函数定义处有个*符号。

    *既可以紧跟在function后面,也可以贴在函数名前。

  • 第二,函数内有yield关键字

    用以中断处理流程,并可以临时对外提供一个返回值。

  • 其它,写法上与普通函数无异

1.3 关于生成器函数的使用

  • 1.像普通函数一样调用,得到的不是任何具体的返回值,而是一个迭代器。(也可以看作是一个状态机)

  • 2.来一脚试试。通过调用得到的迭代器对象上的next()方法,开始得到第一个返回值对象。

  • 3.一直踹。每一次调用next()方法,得到一个结果对象,可以看到上面代码注释中的打印信息。

    其中value即当前获得的值,done即迭代状态,它只有ture/false两种可能,当它变为true,即迭代完成。

2.主流使用方式

正常的使用方式也即良好的实践吧,应该是配合promise来使用的。

来一个简陋的示例:

  1. /* eg.1
  2. * Simple Example of Generator-Function
  3. */
  4. //----------------------------------------
  5. function* func() {
  6. // 这里应该是ajax请求,结果是一个promise对象,简单模拟一下
  7. yield new Promise(function(resolve,reject){
  8. resolve('Hello')
  9. })
  10. // 这里应该是ajax请求,结果是一个promise对象,简单模拟一下
  11. yield new Promise(function(resolve,reject){
  12. resolve('World')
  13. })
  14. }
  15. let g = func()
  16. g.next().value.then((data) => {
  17. console.log('log-1:', data)
  18. return g.next().value
  19. }).then((data) => {
  20. console.log('log-2:', data)
  21. })
  22. // log-1: Hello
  23. // log-2: World
  24. //----------------------------------------

这样,就将异步的ajax处理简单地以同步的样子书写出来了。

3.粗陋的实践

除了可以处理异步,码路工人个人觉得,Generator比较适合用在循环处理的场景。其中就实践过类似下面这个处理的例子:

  1. /* eg.2 (part1)
  2. * My Example of Generator-Function
  3. */
  4. //----------------------------------------
  5. // 以下代码中都省略掉了检测处理
  6. // 首先来一个Gernerator函数
  7. function *getDateInPeriod(from, to, includEnd=false) {
  8. let fromDate = new Date(from)
  9. let toDate = new Date(to)
  10. if(includEnd) {
  11. toDate = addDays(toDate, 1)
  12. }
  13. for(let date = fromDate;date < toDate; date=addDays(date, 1)) {
  14. yield date
  15. }
  16. }
  17. // 上面调用到了工具函数addDays
  18. function addDays(date, days){
  19. date = new Date(date.setDate(date.getDate() + days))
  20. return date
  21. }
  22. //----------------------------------------

然后就是使用了,在循环取值的过程中,会有一些业务处理(同步的或异步的)。

  1. /* eg.2 (part2)
  2. * My Example of Generator-Function
  3. */
  4. //----------------------------------------
  5. let arrDate = getDateInPeriod('2019-06-06', '2019-06-30', true)
  6. let daysInPeriod = arrDate.next()
  7. while(!daysInPeriod.done) {
  8. // 这里是一堆其它业务处理
  9. console.log(daysInperiod)
  10. daysInPeriod = arrDate.next()
  11. }
  12. console.log(daysInperiod)
  13. //----------------------------------------

打印信息结果:

  1. { value: 2019-06-06T00:00:00.000Z, done: false }
  2. { value: 2019-06-07T00:00:00.000Z, done: false }
  3. ...
  4. { value: 2019-06-29T00:00:00.000Z, done: false }
  5. { value: 2019-06-30T00:00:00.000Z, done: false }
  6. { value: undefined, done: true }

上面的例子中,还是同步的方式。也许不是好的用法,但它能告诉你这是一种用法。

4.听说过的实践

这个码工没有实践过,大意是,Generator函数这个语法糖是按照yield将代码分成多个部分,人手工控制执行每一部分,于是,封装一个执行器函数,简化流程控制,使异步编程轻松愉快。

其实,在有了async/await后真的没有这个必要了。

co.js就是一个这种Generator的执行库)

4.其它

除了上面介绍的生成器函数的主要用法,其实还有点其它小特性,码路工人并没有实践过,感觉也不怎么会用到,这里稍作了解即可。

4.1 可以接收由next传递进的参数。

  1. /* eg.3
  2. * parameters
  3. */
  4. //----------------------------------------
  5. function *genFunc(p) {
  6. console.log(`p is ${p}`)
  7. let p1 = yield p
  8. console.log(`p1 is ${p1}`)
  9. let p2 = yield p1
  10. console.log(`p2 is ${p2}`)
  11. }
  12. let gen = genFunc(1)
  13. // 第一次next无法传参到Generator函数,应该由最初的函数调用处传递
  14. gen.next(2)
  15. // 从第二步next() 传的参数,在第一个yield处接收
  16. gen.next(3)

关于给yield传参确实看起来稍微有一点诡异,其实理解了也就不觉得奇怪了。

说明已贴在上面的注释中。

4.2 可以有默认的迭代器了

  1. /* eg.4
  2. * get value by for-of loop
  3. */
  4. //----------------------------------------
  5. function *foo() {
  6. for(let i=0; i<6; i++) {
  7. yield i
  8. }
  9. }
  10. let gen = foo()
  11. for(let item of gen) {
  12. console.log(item)
  13. }
  14. // 打印结果:
  15. // 0
  16. // 1
  17. // 2
  18. // 3
  19. // 4
  20. // 5
  21. //----------------------------------------

总结

关于生成器函数Generator Function就介绍到这里吧,

这要知道有这个语法糖就可以了,反正以后还真不一定用得到

异步处理主要用到的还是Promiseasync/await

以上。

希望对你能有帮助,下期再见。

-END-  


[ES6系列-07]Generator Function: 生成器函数的更多相关文章

  1. [js高手之路] es6系列教程 - 迭代器与生成器详解

    什么是迭代器? 迭代器是一种特殊对象,这种对象具有以下特点: 1,所有对象都有一个next方法 2,每次调用next方法,都会返回一个对象,该对象包含两个属性,一个是value, 表示下一个将要返回的 ...

  2. [ES6系列-02]Arrow Function:Whats this?(箭头函数及它的this及其它)

    [原创] 码路工人 大家好,这里是码路工人有力量,我是码路工人,你们是力量. 如果没用过CSharp的lambda 表达式,也没有了解过ES6,那第一眼看到这样代码什么感觉? /* eg.0 * fu ...

  3. Nodejs与ES6系列3:generator对象

    3.generator对象 Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同.Generator的中文翻译是生成器,它是ECMAScript6(代号harmory) ...

  4. Generator - Python 生成器

    Generator, python 生成器, 先熟悉一下儿相关定义, generator function 生成器函数, 生成器函数是一个在定义体中存有 'yield' 关键字的函数. 当生成器函数被 ...

  5. [js高手之路] es6系列教程 - 迭代器,生成器,for...of,entries,values,keys等详解

    接着上文[js高手之路] es6系列教程 - 迭代器与生成器详解继续. 在es6中引入了一个新的循环结构for ....of, 主要是用来循环可迭代的对象,那么什么是可迭代的对象呢? 可迭代的对象一般 ...

  6. Python系列之 迭代器和生成器

    很多Python的程序员都会混淆 迭代器 和 生成器 的概念和作用,分不清到底两个有什么区别.今天我们来好好说一说这两个概念. 迭代器(Iterator) Iterator Pattern Itera ...

  7. ES6新特性之生成器函数 (generator function): function*

    一.什么是生成器函数(generator function)? 生成器函数是ES6的新特性之一,它是一个在执行时能中途暂时退出,后面重新调用又能重新进入继续执行的一种函数. 并且在函数内定义的变量的所 ...

  8. ES6笔记(5)-- Generator生成器函数

    系列文章 -- ES6笔记系列 接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术. 在异步编程中,还 ...

  9. ES6生成器函数generator

    ES6生成器函数generator generator是ES6新增的一个特殊函数,通过 function* 声明,函数体内通过 yield 来指明函数的暂停点,该函数返回一个迭代器,并且函数执行到 y ...

随机推荐

  1. OpenRASP管理后台安装记录

    OpenRASP项目地址https://rasp.baidu.com/ 一.安装java 在CentOS中安装ElasticSearch需要Java1.8.0,可执行命令java -version查看 ...

  2. How to get binary string from ArrayBuffer?

    https://stackoverflow.com/questions/16363419/how-to-get-binary-string-from-arraybuffer https://stack ...

  3. Linked List-3

    第一篇终结Linked List(一).终结Linked List(二)主要讲了单链表的基础知识,接下来的第二篇主要讲一些比较经典的问题. 一.Count() 给一个单链表和一个整数,返回这个整数在链 ...

  4. CodeForces - 260B

    A recently found Ancient Prophesy is believed to contain the exact Apocalypse date. The prophesy is ...

  5. 关于RMQ问题的四种解法

    什么是RMQ问题:     RMQ (Range Minimum/Maximum Query):对于长度为n的数组A,回答若干询问RMQ(A,i,j)(i,j<=n-1),返回数组A中下标在i, ...

  6. jquery 根据后端传过来的value值,让小原点根据不同值区间去左右定位

    /** * 小圆点滑动 * @param {目标dom} barEle * @param {最小值} min * @param {最大值} max * @param {dom总长度} domLang ...

  7. 聊聊算法——BFS和DFS

    如果面试字节跳动和腾讯,上来就是先撕算法,阿里就是会突然给你电话,而且不太在意是周末还是深夜, 别问我怎么知道的,想确认的可以亲自去试试.说到算法,直接力扣hard三百题也是可以的,但似乎会比较伤脑, ...

  8. 你应该知道的Vue高级特性

    本文使用的Vue版本:2.6.10 Vue为我们提供了很多高级特性,学习和掌握它们有助于提高你的代码水平. 一.watch进阶 从我们刚开始学习Vue的时候,对于侦听属性,都是简单地如下面一般使用: ...

  9. spring学习笔记(七)HttpMessageConverter

    spring学习笔记(七)HttpMessageConverter 1. HttpMessageConverter的加载 2. 从StringMessageConverter探究消息转换器的原理 1. ...

  10. 201771010113 李婷华《面向对象程序设计(Java)》第十二周总结

    一.理论知识部分 1.Java的抽象口工具箱( Abstract WindowToolkit, AWT)包含在java.awt包中,它提供了许多用来设计GUI的组件类和容器类. 2.AWT库处理用户界 ...