本文共 7338 字,大约阅读时间需要 24 分钟。
es6 generator
by Tiago Lopes Ferreira
由Tiago Lopes Ferreira
Generators are .
生成器是对象 。
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?
异步开发在这里听起来很熟悉吗?
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
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*
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 are simple iterables, which means that they follow the iterable
and iterator
protocols:
生成器是简单的iterables ,这意味着它们遵循iterable
和iterator
协议:
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
)迭代生成器的值。
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-of
或destructuring
类的已定义数据使用者时,返回值将被忽略。
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.
它还允许我们存储执行的生成器返回的值。
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
。
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.
这里有一些有趣的要点。
At this stage we are creating our generator g
.
在此阶段,我们正在创建生成器g
。
Our execution stops at point A
.
我们的执行在A
点停止。
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
。
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
挂起。
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
暂停生成器的执行,并且在每次迭代时,生成器都会从暂停的位置恢复,这很有用。
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 example on .
接下来是一个示例,该示例使用我们知道的带有promises
的JSON文件。 我们将在上使用示例。
Using and a generator our code will look more like synchronous code.
使用和生成器,我们的代码将看起来更像同步代码。
As for the new async/await
our code will look a lot like our previous version.
至于新的async/await
我们的代码看起来很像我们以前的版本。
This is schema, made by on show us how generators relate with iterators.
这是由在“ 制作的模式,向我们展示了生成器与迭代器之间的关系。
Generators are an implementation of iterables and follow the iterable
and iterator
protocol. Therefore they can be used to build iterables.
生成器是可迭代的实现,并遵循iterable
和iterator
协议。 因此,它们可用于构建可迭代对象。
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.
生成器是使异步开发接近于同步的下一步。
for his
的
for his
(
for his promises example on
( 在承诺示例
To all fans
致所有迷
Be sure to check out my other articles on ES6
请务必查看我有关ES6的其他文章
翻译自:
es6 generator
转载地址:http://uzyzd.baihongyu.com/