es6 generator_让我们探索一下ES6 Generators

es6 generator

by Tiago Lopes Ferreira

由Tiago Lopes Ferreira

让我们探索一下ES6 Generators (Let’s explore ES6 Generators)

Generators are an implementation of iterables.

生成器是可迭代对象的实现

The big deal about generators is that they are functions that can suspend its execution while maintaining the context.

生成器的重要之处在于它们是可以在保持上下文的同时暂停其执行的函数

This behaviour is crucial when dealing with executions that need to be paused, but its context maintained in order to recover it in the future.

在处理需要暂停的执行时,此行为至关重要,但是为了保持将来的恢复状态,必须保留其上下文。

Does async development sounds familiar here?

异步开发在这里听起来很熟悉吗?

句法 (Syntax)

The syntax for generators starts with it’s function* declaration (please note the asterisk) and the yield through which a generator can pause it’s execution.

生成器的语法从其function*声明(请注意星号 )和生成器可以暂停其执行的yield

Calling our generator function creates new generator that we can use to control the process through next function.

调用generator函数将创建新的生成器,我们可以使用它通过next函数来控制过程。

Running next will execute our generator’s code until an yield expression is reached.

next运行将执行generator的代码,直到达到yield表达式为止。

At this point the value on yield is emitted and the generator’s execution is suspended.

此时,将发出yield值,并暂停generator的执行。

(yield)

yield was born with generators and allow us to emit values. However, we can only do this while we are inside a generator.

yield是由发电机产生的,它使我们能够发出价值。 但是,只有在发电机内部时才能执行此操作。

If we try to yield a value on a callback, for instance, even if declared inside the generator, we will get an error.

例如,如果我们尝试在回调中yield一个值,即使在生成器中声明了该值,我们也会收到错误消息。

让* (yield*)

yield* was built to enable calling a generator within another generator.

yield*是为了能够在另一个生成器中调用生成器而构建的。

Our b iterator, produced by bar generator, does not work as expected when calling foo.

bar生成器生成的b迭代器在调用foo时无法按预期工作。

This is because, although the execution of foo produces an iterator, we do not iterate over it.

这是因为,尽管foo的执行会产生一个迭代器,但我们不会对其进行迭代。

That’s why ES6 brought the operator yield*.

这就是ES6带给运营商yield*

This works perfectly with data consumers.

这非常适合数据使用者。

Internally yield* goes over every element on the generator and yield it.

内部yield*遍历生成器上的每个元素并yield它。

生成器作为迭代器 (Generators as Iterators)

Generators are simple iterables, which means that they follow the iterable and iterator protocols:

生成器是简单的iterables ,这意味着它们遵循iterableiterator协议:

  • The iterable protocol says that an object should return a function iterator whose key is Symbol.iterator.

    iterable协议表示对象应返回其键为Symbol.iterator的函数迭代器。

  • The iterator protocol says that the iterator should be an object pointing to the next element of the iteration. This object should contain a function called next.

    iterator协议说迭代器应该是一个指向迭代的下一个元素的对象。 该对象应包含一个名为next的函数。

Because generators are iterables then we can use a data consumer, e.g. for-of, to iterate over generators’ values.

由于生成器是可迭代的,因此我们可以使用数据使用者(例如for-of )迭代生成器的值。

返回 (Return)

We can add a return statement to our generator, however return will behave differently according to the way generators’ data is iterated.

我们可以在生成器中添加return语句,但是return会根据生成器数据的迭代方式而有所不同。

When performing the iteration by hand, using next, we get our returned value (i.e. done) as the last value of our iterator object and our done flag as true.

手动执行迭代时,使用next ,我们获得返回值(即done )作为迭代器对象的最后一个value ,并且done标志为true。

On the side, when using a defined data consumer such as for-of or destructuring, the returned value is ignored.

在另一方面,当使用诸如for-ofdestructuring类的已定义数据使用者时,返回值将被忽略。

让* (yield*)

We saw that yield* allows us to call a generator inside a generator.

我们看到yield*允许我们在生成器内部调用生成器。

It also allow us to store the value returned by the executed generator.

它还允许我们存储执行的生成器返回的值。

(Throw)

We can throw inside a generator and next will propagate our exception.

我们可以throw放入生成器中,然后next将传播异常。

As soon as an exception is thrown the iterator flow breaks and it’s state is set to done: true indefinitely.

一旦引发异常,迭代器流程就会中断,并且其状态将设置为done: true无限期为done: true

生成者作为数据消费者 (Generators as Data Consumers)

Besides generators being data producers, through yield, they also have the ability to consume data using next.

除了生成器是数据生成器之外,它们还可以通过yield来使用next来使用数据。

There’s some interesting points to explore here.

这里有一些有趣的要点。

生成器创建(1) (Generator Creation (1))

At this stage we are creating our generator g.

在此阶段,我们正在创建生成器g

Our execution stops at point A.

我们的执行在A点停止。

第一下一个(2) (First next (2))

The first execution of next gets our generator to be executed until the first yield statement.

next的第一次执行使生成器一直执行到第一个yield语句。

On this first execution any value sent through next is ignored. This is because there’s no yield statement until the first yield statement ?

在第一次执行时,将忽略通过next发送的任何值。 这是因为没有yield的语句,直到第一个yield语句?

Our execution suspends at B waiting for a value to be filled to yield.

我们的执行在B暂停,等待填充一个值以yield

下一个下一个(3) (Next next (3))

On the next executions of next our generator will run the code until the next yield.

在next的next一次执行中,我们的生成器将运行代码,直到下一个yield为止。

In our case, it logs the value that is got through yield (i.e. Got: foo) and it gets suspended again on yield.

在我们的例子中,它记录通过yield获得的值(即Got: foo ),并再次在yield挂起。

用例 (Use Cases)

实施可迭代 (Implement Iterables)

Because generators are an iterable implementation, when created we get an iterable object, where each yield represents the value to emitted on each iteration. This description allow us to use generators to create iterables.

因为生成器是一个可迭代的实现 ,所以在创建时,我们得到一个可迭代的对象,其中每个yield表示每次迭代要发出的值。 此描述使我们可以使用生成器来创建可迭代对象。

The following example represents a generator as iterable that iterates over even numbers until max is reached. Because our generator returns an iterable we can use for-of to iterate over the values.

下面的示例将生成器表示为可迭代的生成器,该生成器将对偶数进行迭代直到达到max 。 因为我们的生成器返回一个可迭代的对象,所以我们可以使用for-of来迭代这些值。

It’s useful to remember that yield pauses the generator’s execution, and on each iteration the generator resumes from where it was paused.

记住, yield暂停生成器的执行,并且在每次迭代时,生成器都会从暂停的位置恢复,这很有用。

异步代码 (Asynchronous Code)

We can use generators to better work with async code, such as promises.

我们可以使用生成器更好地处理异步代码,例如promises

This use case it a good introduction to the new async/await on ES8.

这个用例很好地介绍了ES8上的新async/await

Next is an example of fetching a JSON file with promises as we know it. We will use Jake Archibald example on developers.google.com.

接下来是一个示例,该示例使用我们知道的带有promises的JSON文件。 我们将在developers.google.com上使用Jake Archibald示例。

Using co library and a generator our code will look more like synchronous code.

使用co库和生成器,我们的代码将看起来更像同步代码。

As for the new async/await our code will look a lot like our previous version.

至于新的async/await我们的代码看起来很像我们以前的版本。

结论 (Conclusion)

This is schema, made by Axel Rauschmayer on Exploring ES6 show us how generators relate with iterators.

这是由Axel Rauschmayer在“ 探索ES6”中制作的模式,向我们展示了生成器与迭代器之间的关系。

Generators are an implementation of iterables and follow the iterable and iterator protocol. Therefore they can be used to build iterables.

生成器是可迭代的实现,并遵循iterableiterator协议。 因此,它们可用于构建可迭代对象。

The most amazing thing about generators is their ability to suspend their execution. For this ES6 brings a new statement called yield.

生成器最令人惊讶的是它们具有暂停执行的能力。 为此,ES6带来了一个称为yield的新声明。

However, calling a generator inside a generator is not as easy as executing the generator function. For that, ES6 has yield*.

但是,在生成器内部调用生成器并不像执行生成器功能那样容易。 为此,ES6具有yield*

Generators are the next step to bring asynchronous development close to synchronous.

生成器是使异步开发接近于同步的下一步。

谢谢 ? (Thanks to ?)

Be sure to check out my other articles on ES6

请务必查看我有关ES6的其他文章

Demystifying ES6 Iterables & IteratorsLet’s demystify JavaScript new way to interact with data structures.medium.freecodecamp.com

揭开ES6迭代器和迭代器 的神秘 面纱 让我们揭开JavaScript与数据结构交互的新方式的神秘 面纱 medium.freecodecamp.com

翻译自: https://www.freecodecamp.org/news/lets-explore-es6-generators-5e58ed23b0f1/

es6 generator

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值