ES6中的迭代器、Generator函数及Generator函数的异步操作方法


Posted in Javascript onMay 12, 2019

最近在写RN相关的东西,其中涉及到了redux-saga ,saga的实现原理就是ES6中的Generator函数,而Generator函数又和迭代器有着密不可分的关系。所以本篇博客先学习总结了iterator相关的东西,然后又介绍了Generator相关的内容,最后介绍了使用Generator进行异步编程。本篇博客所涉及的示例使用TypeScript语言编写,当然所涉及的特性是基于ES6规范的,使用TS语言不影响来阐述和总结ES6的相关特性。下篇博客准备系统梳理一下saga相关的内容。

一、迭代器

之前再聊迭代器模式时,使用Swift语言自定义过迭代器,在TS中也有迭代器。此处的迭代器与之前所介绍的迭代器是大同小异的。首先我们先来自定义一个迭代器,然后再看一下ES6中的迭代器的使用方式。

1、自定义迭代器

下方定义了一个迭代器函数,函数说明如下:

  • 该函数接收一个数组类型的参数,我们可以将需要创建迭代器的数组作为参数传进来。
  • 函数内部定义了一个 nextIndex 参数用来记录迭代器的位置。
  • 该函数返回一个迭代器对象,该迭代器对象包含一个key为 next , value为匿名函数的属性。
  • 这个key为 next 的匿名方法的返回值为每次迭代器的返回结果对象,这个结果对象由 两个属性组成,value表示本次迭代器的值,done表示迭代器遍历是否结束。遍历到最后,最终返回的值为 { value: undefine, done: true }, 也就意味着迭代器遍历结束,value是undefined, done为true。 

 

ES6中的迭代器、Generator函数及Generator函数的异步操作方法

自定义完迭代器后,我们就可以对上述代码进行测试了。

首先创建了一个数组,然后将数组传给 makeIterator 函数。

而 makeIterator 函数会返回一个含有next方法的迭代器对象。

  • 我们将这个迭代器对象命名为 iterator,我们就可以通过 iterator的next方法来依次获取数组中的值了。
  • 我们通过 while 循环来不断的调用 iterator中的next方法,直到next方法返回的对象中的done值为true时,表示遍历结束。
  • 遍历结束后,我们再次调用 next() 方法,得到的是{ value: undefind, done: true } 的对象,表示遍历结束,获取的value值为 undefined。

ES6中的迭代器、Generator函数及Generator函数的异步操作方法2、2。ES6中的迭代器

类似于Swift语言的特性,ES6规范中我们可以直接通过一些对象获取该对象所对应的迭代器,如下所示:

下方示例中使用的数组和上面使用的list是一个,首先我们通过 list[Symbol.iterator]() 的方式获取了 list对应的迭代器。

(Symbol也是一种数据类型, 该数据类型用来表示独一无二的对象)该迭代器的使用方式和输出结果与上述我们自定义的迭代器的使用方式完全一致, 输出结果与之前的结果也是一致的。

ES6中的迭代器、Generator函数及Generator函数的异步操作方法

3、使用 for - of 遍历迭代器

上述方式创建的迭代器我们是使用的while循环来进行遍历的,除了while循环,我们还可以通过for-of 进行遍历。

此处的 for - of遍历方式类似于Swift语言中的 for - in循环,可以依次的自动去除迭代器中的值。

下方就是使用for - of 来循环遍历创建的迭代器。

从下方示例中我们不难看出直接输出的是迭代器返回对象的value值。

ES6中的迭代器、Generator函数及Generator函数的异步操作方法

4、在类中添加迭代器

我们可以在自己的类中添加相关方法,使我们自己的类支持迭代器。下方就创建了一个 RangeIterator 类,该类的作用是可以定义一个范围,构造器可以接受两个值,一个是范围的起始位置另一个是范围的结束点。下方我们为该范围类添加了自定义迭代器,具体说明如下:

在该类中添加了一个名为 next 的箭头函数,在该函数中做的事情与之前我们自定义的next方法差不多,主要是用来获取下一个值然后返回。

然后又实现一个[Symbole.iterator]函数,用来获取迭代器对象。最后我们可看到定义的范围对象可以向迭代器那样使用for-of进行遍历。

ES6中的迭代器、Generator函数及Generator函数的异步操作方法

5、调用迭代器的场景

迭代器的使用场景还是蛮多的,解构赋值、扩展运算符、Generator函数、yield*, 下方会简单的列举出来。

(1)、对数组或者集合的解构赋值

在下方代码片段中首先创建了一个名为 mySet 的集合对象。然后通过循环给集合中添加了一些值。然后通过 解构赋值 的形式,取出了 mySet 中的第一个值和第二个值。此刻的结构赋值会调用集合的迭代器接口,取出第一个值和第二个值,分别赋值给 first 和 second。

第二个红框中在结构赋值是使用了扩展运算符,该操作符会使 others 接收 firstItem 剩下的值。

ES6中的迭代器、Generator函数及Generator函数的异步操作方法

(2)、扩展运算符 ...

接下来来看另一个扩展运算符的例子。

首先定义了一个字符串,然后通过扩展运算符将该字符串的每个字符拆分到一个数组中,输出结果如下所示。扩展运算符还可以使用到对象上,如第二个示例所示。

ES6中的迭代器、Generator函数及Generator函数的异步操作方法

(3)、在Generator函数的 yield * 中使用

稍后会详细的介绍 Generator 函数,一个Generator 函数返回的是一个迭代器,我们可以调用该迭代器的 next 方法来执行每一个 yield。在 Generator 函数中,可以使用 yield * 后边跟一个可便遍历的结构,这样我们就可以在外部统一使用 next 来访问这个可遍历的结构的每一个值,如下所示:

ES6中的迭代器、Generator函数及Generator函数的异步操作方法

二、Generator函数及异步编程

理解完迭代器,接下来来看一下Generator函数。如果做过RN开发的话,如果使用过 redux - saga的话,应该对Generator函数不陌生。Generator函数是ES6提供的异步编程的解决方案,解析了我们先看一下Generator函数基本使用方式,再看一下如何使用Generator函数进行异步编程。

1、Generator函数的定义和使用

下方定义了一个 Generator函数,Generator函数的定义与普通函数的定义差不多,只不过是function关键字后边跟了一个*号。然后函数体内部使用了一个个 yield语句来表明每一步的操作。定义完Generator函数后,下方紧接着的是使用,首先调用该Generator函数获取了一个迭代器,每次执行这个迭代器的next方法都会一次的执行一个yield语句。输出结果和上面的迭代器没啥区别。

ES6中的迭代器、Generator函数及Generator函数的异步操作方法

2、next的参数

在调用Generator函数返回的迭代器时,是可以往next方法中传入参数的。next 方法可以带一个参数,该参数被当做上一个 yield 语句的返回值。下方就是给 next 传参的一个示例:

下方定义了一个Generator函数,用来输出自增的值,每次调用next都会获取一个自增的值。当调用 rg.next(true) 时,这个true就会被赋值给 reset, 因为这个reset被视为上个yield的返回值,上一个yield执行后,会将index设置为 -1。那么rg.next(true)对应的 yield执行是,index是从 -1 开始自增的,自增后为0,所以 rg.next(true) 对应的 yield 的值为0。

ES6中的迭代器、Generator函数及Generator函数的异步操作方法

下方是另一个示例:

下方定义了一个名为testNextValue的Generator函数,该函数本身接收了一个参数。在调用该Generator函数时,传入了一个参数,这个参数不是Next的参数,是Generator函数本身的参数。

Generator函数在调用时,函数体并不会马上执行,在调用next函数时才会执行函数中yield语句体。

第一次调用Next,给Next传入了一个值 5,也就是说明 x = 5。

第一次执行next会调用第一个 yield 语句体,test1.next(2) = x + 1 = 5 + 1 = 6, 所以第一次调用next的结果值为

6。第二次调用 Next,传入的Next参数为3。

这个3 被作为上一个 yield 语句体的返回值,yield(x + 1) 的返回值为 3。那么 y 的值就为 2 * 3 = 6。yield中的值为 y / 3 = 2,所以第二次执行next获取的值为 2。第三次调用Next传入的参数为 4,这个 4 被作为上个yield语句体返回的参数,所以z = 4, 上分析过了 x = 5, y = 6, 所以 x + y + z = 15, 第三次执行next为 15。再次调用Next,因为语句体执行完了,所以获取到的是undefined。

ES6中的迭代器、Generator函数及Generator函数的异步操作方法

三、使用Generator函数进行异步编程

接下来实现一个简单的示例,使用Generator函数结合Promise回调模拟一下异步编程。

首先定义了一个 getPromise函数,该函数接收两个参数,一个参数表示网络请求的参数,另一个参数表示请求时间。该函数返回一个 Promise对象,在Promise对象中我们使用了setTimeout来模拟请求的延迟,根据传入的timeout来决定延迟时间,延迟时间到达后会执行 resolve方法,将相关值回调出来。

ES6中的迭代器、Generator函数及Generator函数的异步操作方法

然后定义了一个Generator函数,在该函数中通过yield来调用每个函数,下方的Generator函数比较简单,在此就不做过多赘述了。

ES6中的迭代器、Generator函数及Generator函数的异步操作方法

然后我们通过for -of 一次执行Generator函数的next方法,进而来执行每个getPromise方法。

ES6中的迭代器、Generator函数及Generator函数的异步操作方法

下方是具体的执行结果,从执行结果中不难看出,每次获取的yield值是一个Promise对象,我们可在该Promise对象的then方法中获取到相关的结果值。从输出顺序中可以看出,会先输出时间小的那个结果。

ES6中的迭代器、Generator函数及Generator函数的异步操作方法

总结

以上所述是小编给大家介绍的ES6中的迭代器、Generator函数及Generator函数的异步操作,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Javascript 相关文章推荐
用js得到网页中所有的div的id
Oct 19 Javascript
js实现的map方法示例代码
Jan 13 Javascript
JavaScript eval() 函数介绍及应用示例
Jul 29 Javascript
javascript去除空格方法小结
May 21 Javascript
JavaScript事件类型中焦点、鼠标和滚轮事件详解
Jan 25 Javascript
学习javascript文件加载优化
Feb 19 Javascript
详解JSON Web Token 入门教程
Jul 30 Javascript
JS实现点击拉拽轮播图pc端移动端适配
Sep 05 Javascript
Vue 配合eiement动态路由,权限验证的方法
Sep 26 Javascript
详解微信小程序之scroll-view的flex布局问题
Jan 16 Javascript
vue项目中全局引入1个.scss文件的问题解决
Aug 01 Javascript
Vue 设置axios请求格式为form-data的操作步骤
Oct 29 Javascript
浅谈vue.use()方法从源码到使用
May 12 #Javascript
Vue安装浏览器开发工具的步骤详解
May 12 #Javascript
微信小程序缓存过期时间的使用详情
May 12 #Javascript
从0到1搭建element后台框架优化篇(打包优化)
May 12 #Javascript
Vue项目服务器部署之子目录部署方法
May 12 #Javascript
vue配置接口域名方法总结
May 12 #Javascript
详解babel升级到7.X采坑总结
May 12 #Javascript
You might like
十大催泪虐心动漫电影,有几部你还没看
2020/03/04 日漫
php mysql索引问题
2008/06/07 PHP
php求正负数数组中连续元素最大值示例
2014/04/11 PHP
php文件服务实现虚拟挂载其他目录示例
2014/04/17 PHP
php 遍历目录,生成目录下每个文件的md5值并写入到结果文件中
2016/12/12 PHP
PHP正则表达式函数preg_replace用法实例分析
2020/06/04 PHP
PHP 99乘法表的几种实现代码
2020/10/13 PHP
腾讯与新浪的通过IP地址获取当前地理位置(省份)的接口
2010/07/26 Javascript
js/jQuery对象互转(快速操作dom元素)
2013/02/04 Javascript
javascript生成json数据简单示例分享
2014/02/14 Javascript
php中给js数组赋值方法
2014/03/10 Javascript
jQuery中size()方法用法实例
2014/12/27 Javascript
javascript判断css3动画结束 css3动画结束的回调函数
2015/03/10 Javascript
JavaScript面对国际化编程时的一些建议
2015/06/24 Javascript
用js实现每隔一秒刷新时间的实例(含年月日时分秒)
2017/10/25 Javascript
vue中keep-alive的用法及问题描述
2018/05/15 Javascript
jQuery实现左右两个列表框的内容相互移动功能示例
2019/01/27 jQuery
Vue实现购物车实例代码两则
2020/05/30 Javascript
Element Breadcrumb 面包屑的使用方法
2020/07/26 Javascript
微信小程序实现可长按移动控件
2020/11/01 Javascript
[51:22]Fnatic vs IG 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
[02:53]2018年度DOTA2最佳战队-完美盛典
2018/12/17 DOTA
用Python删除本地目录下某一时间点之前创建的所有文件的实例
2017/12/14 Python
Python使用requests发送POST请求实例代码
2018/01/25 Python
Python实现正弦信号的时域波形和频谱图示例【基于matplotlib】
2018/05/04 Python
python移位运算的实现
2019/07/15 Python
Python实现串口通信(pyserial)过程解析
2019/09/25 Python
python实现XML解析的方法解析
2019/11/16 Python
python实现梯度下降和逻辑回归
2020/03/24 Python
IE下实现类似CSS3 text-shadow文字阴影的几种方法
2011/05/11 HTML / CSS
Meli Melo官网:名媛们钟爱的英国奢侈手包品牌
2017/04/17 全球购物
Omio俄罗斯:一次搜索公共汽车、火车和飞机的机票
2018/11/17 全球购物
淘宝网店营销策划书
2014/01/11 职场文书
中层干部竞争上岗演讲稿
2014/01/13 职场文书
2015年安全教育月活动总结
2015/03/26 职场文书
理解python中装饰器的作用
2021/07/21 Python