ES6迭代器与Generator函数详解:从原理到异步编程实战

作者:木棉时间:2026-10-23 07:08:09浏览:456

本文深入解析ES6中的迭代器与Generator函数,阐述其在Redux-Saga等库中的底层原理。通过自定义迭代器、Symbol.iterator接口及for-of遍历,详解迭代器工作模式。重点讲解Generator函数的yield机制、next传参逻辑,并结合Promise模拟异步流程,为理解现代JavaScript异步解决方案奠定基础。

引言:从Redux-Saga看Generator与迭代器

近期在开发React Native应用时涉及Redux-Saga,其核心实现依赖于ES6的Generator函数,而Generator函数与迭代器(Iterator)紧密相关。因此,本文首先梳理迭代器的相关知识,随后介绍Generator函数的用法,最后探讨如何利用Generator进行异步编程。示例代码采用TypeScript编写,基于ES6规范,TypeScript的使用不影响对ES6特性的阐述。后续将专门梳理Saga的相关内容。

一、迭代器基础

一、迭代器

此前在讨论迭代器模式时,曾使用Swift语言自定义过迭代器。在TypeScript中同样存在迭代器概念,其原理与之前介绍的迭代器模式基本一致。本文将先演示如何自定义迭代器,再介绍ES6中迭代器的标准用法。

1. 自定义迭代器实现

1、自定义迭代器

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

  • 该函数接收一个数组作为参数,用于指定需要创建迭代器的数据源。
  • 函数内部定义了一个nextIndex变量,用于记录当前迭代的位置。
  • 该函数返回一个迭代器对象,该对象包含一个key为next、value为匿名函数的属性。
  • key为next的匿名函数每次调用时返回一个结果对象,该对象由两个属性组成:value表示当前迭代的值,done表示遍历是否结束。当遍历结束时,最终返回 { value: undefine, done: true },即value为undefined,done为true。

 

引言:从Redux-Saga看Generator与迭代器

定义完自定义迭代器后,我们可以对代码进行测试验证。

首先创建一个数组,并将其作为参数传递给makeIterator函数。

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

  • 将该迭代器对象命名为iterator,即可通过iterator的next方法依次获取数组中的元素值。
  • 使用while循环不断调用iterator的next方法,直到返回对象中的done值为true,表示遍历结束。
  • 遍历结束后再次调用next()方法,将得到{ value: undefined, done: true }的对象,表明遍历已结束,且获取的value值为undefined。

2. ES6标准迭代器与Symbol.iterator

引言:从Redux-Saga看Generator与迭代器2、ES6中的迭代器

类似于Swift语言的特性,ES6规范允许直接通过特定对象获取其对应的迭代器,示例如下:

下方示例中使用的数组与前述list相同,首先通过 list[Symbol.iterator]() 的方式获取了list对应的迭代器。

(Symbol是一种数据类型,用于表示独一无二的对象)该迭代器的使用方式及输出结果与自定义迭代器完全一致,输出结果也相同。

引言:从Redux-Saga看Generator与迭代器

3. for-of遍历与类中迭代器应用

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

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

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

下方展示了使用for-of循环遍历所创建的迭代器。

从下方示例可以看出,直接输出的是迭代器返回对象中的value值。

引言:从Redux-Saga看Generator与迭代器

4、在类中添加迭代器

我们可以在自定义类中添加相关方法,使该类支持迭代器协议。下方创建了一个RangeIterator类,该类用于定义一个数值范围,构造函数接收两个参数:范围的起始位置和结束点。下方为该范围类添加了自定义迭代器,具体说明如下:

在该类中添加了一个名为next的箭头函数,其功能与之前自定义的next方法类似,主要用于获取下一个值并返回。

同时实现了一个[Symbole.iterator]函数,用于获取迭代器对象。最后可以看到,定义的范围对象可以像迭代器一样使用for-of进行遍历。

引言:从Redux-Saga看Generator与迭代器

4. 迭代器的常见应用场景

5、调用迭代器的场景

迭代器的应用场景广泛,包括解构赋值、扩展运算符、Generator函数以及yield*等,下方将简要列举这些场景。

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

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

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

引言:从Redux-Saga看Generator与迭代器

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

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

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

引言:从Redux-Saga看Generator与迭代器

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

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

引言:从Redux-Saga看Generator与迭代器

二、Generator函数详解

二、Generator函数及异步编程

理解迭代器后,接下来来看Generator函数。如果从事过React Native开发并使用过Redux-Saga,应该对Generator函数并不陌生。Generator函数是ES6提供的异步编程解决方案,下面我们先看Generator函数的基本使用方式,再探讨如何使用Generator函数进行异步编程。

1. Generator定义与基本使用

1、Generator函数的定义和使用

下方定义了一个Generator函数,其定义与普通函数类似,只是在function关键字后跟了一个*号。函数体内部使用yield语句来表明每一步的操作。定义完Generator函数后,紧接着是使用示例:首先调用该Generator函数获取一个迭代器,每次执行该迭代器的next方法都会依次执行一个yield语句。输出结果与前述迭代器无异。

引言:从Redux-Saga看Generator与迭代器

2. next方法传参机制

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。

引言:从Redux-Saga看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。

引言:从Redux-Saga看Generator与迭代器

三、Generator在异步编程中的应用

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

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

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

引言:从Redux-Saga看Generator与迭代器

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

引言:从Redux-Saga看Generator与迭代器

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

引言:从Redux-Saga看Generator与迭代器  

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

引言:从Redux-Saga看Generator与迭代器

总结

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

作者最新文章