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 相关文章推荐
javascript 支持链式调用的异步调用框架Async.Operation
Aug 04 Javascript
写入cookie的JavaScript代码库 cookieLibrary.js
Oct 24 Javascript
jQuery中:enabled选择器用法实例
Jan 04 Javascript
jQuery实现6位数字密码输入框
Dec 29 Javascript
js获取浏览器的各种属性
Apr 27 Javascript
JS鼠标滚动分页效果示例
Jul 05 Javascript
基于AngularJS实现表单验证功能
Jul 28 Javascript
解决vue中对象属性改变视图不更新的问题
Feb 23 Javascript
详解vue表单——小白速看
Apr 08 Javascript
浅谈JavaScript 代码整洁之道
Oct 23 Javascript
详解element-ui中表单验证的三种方式
Sep 18 Javascript
vue-router 2.0 跳转之router.push()用法说明
Aug 12 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
用PHP和ACCESS写聊天室(一)
2006/10/09 PHP
删除及到期域名的查看(抢域名必备哦)
2008/05/14 PHP
PHP的SQL注入过程分析
2012/01/06 PHP
一张表搞清楚php is_null、empty、isset的区别
2015/07/07 PHP
YII2框架中添加自定义模块的方法实例分析
2020/03/18 PHP
TNC vs BOOM BO3 第三场2.13
2021/03/10 DOTA
任意位置显示html菜单
2007/02/01 Javascript
jQuery语法总结和注意事项小结
2012/11/11 Javascript
JavaScript常用全局属性与方法记录积累
2013/07/03 Javascript
原生JS实现表单checkbook获取已选择的值
2013/07/21 Javascript
jquery事件与函数的使用介绍
2013/09/29 Javascript
Javascript基础教程之数据类型 (字符串 String)
2015/01/18 Javascript
JS实现简单的图书馆享元模式实例
2015/06/30 Javascript
WordPress中鼠标悬停显示和隐藏评论及引用按钮的实现
2016/01/12 Javascript
javascript实现dom元素可拖动
2016/03/21 Javascript
浅谈vue项目优化之页面的按需加载(vue+webpack)
2017/12/11 Javascript
JS返回页面时自动回滚到历史浏览位置
2018/09/26 Javascript
详解vue-cli 2.0配置文件(小结)
2019/01/14 Javascript
如何使用CSS3+JQuery实现悬浮墙式菜单
2019/06/18 jQuery
vue-preview动态获取图片宽高并增加旋转功能的实现
2020/07/29 Javascript
Python使用ntplib库同步校准当地时间的方法
2016/07/02 Python
python 输入一个数n,求n个数求乘或求和的实例
2018/11/13 Python
Python中利用aiohttp制作异步爬虫及简单应用
2018/11/29 Python
python selenium firefox使用详解
2019/02/26 Python
简单了解django处理跨域请求最佳解决方案
2020/03/25 Python
分享30个新鲜的CSS3打造的精美绚丽效果(附演示下载)
2012/12/28 HTML / CSS
html5 touch事件实现触屏页面上下滑动(二)
2016/03/10 HTML / CSS
Raffaello Network德国:意大利拉斐尔时尚购物网
2019/05/01 全球购物
师范应届生教师求职信
2013/11/05 职场文书
中专生职业生涯规划书范文
2013/12/29 职场文书
一份婚庆公司创业计划书
2014/01/11 职场文书
中国好声音广告词
2014/03/18 职场文书
我的小天地教学反思
2014/04/30 职场文书
离婚财产处理协议书
2014/09/30 职场文书
杜甫草堂导游词
2015/02/03 职场文书
考研经验交流会策划书
2015/11/02 职场文书