You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/12-generators-iterators/1-generators/article.md
+11-11
Original file line number
Diff line number
Diff line change
@@ -40,7 +40,7 @@ The function code execution hasn't started yet:
40
40
41
41

42
42
43
-
The main method of a generator is `next()`. When called, it runs the execution till the nearest `yield <value>` statement (`value` can be omitted, then it's `undefined`). Then the function execution pauses, and the yielded `value` is returned to the outer code.
43
+
The main method of a generator is `next()`. When called, it runs the execution until the nearest `yield <value>` statement (`value` can be omitted, then it's `undefined`). Then the function execution pauses, and the yielded `value` is returned to the outer code.
44
44
45
45
The result of `next()` is always an object with two properties:
Now the generator is done. We should see it from `done:true` and process `value:3` as the final result.
92
92
93
-
New calls `generator.next()` don't make sense any more. If we do them, they return the same object: `{done: true}`.
93
+
New calls to `generator.next()` don't make sense any more. If we do them, they return the same object: `{done: true}`.
94
94
95
95
```smart header="`function* f(…)` or `function *f(…)`?"
96
96
Both syntaxes are correct.
@@ -154,7 +154,7 @@ let sequence = [0, ...generateSequence()];
154
154
alert(sequence); // 0, 1, 2, 3
155
155
```
156
156
157
-
In the code above, `...generateSequence()` turns the iterable generator object into array of items (read more about the spread operator in the chapter [](info:rest-parameters-spread-operator#spread-operator))
157
+
In the code above, `...generateSequence()` turns the iterable generator object into an array of items (read more about the spread operator in the chapter [](info:rest-parameters-spread-operator#spread-operator))
That works, because `range[Symbol.iterator]()` now returns a generator, and generator methods are exactly what `for..of` expects:
215
-
- it has `.next()` method
215
+
- it has a `.next()` method
216
216
- that returns values in the form `{value: ..., done: true/false}`
217
217
218
-
That's not a coincidence, of course. Generators were added to JavaScript language with iterators in mind, to implement them easier.
218
+
That's not a coincidence, of course. Generators were added to JavaScript language with iterators in mind, to implement them easily.
219
219
220
220
The variant with a generator is much more concise than the original iterable code of `range`, and keeps the same functionality.
221
221
222
222
```smart header="Generators may generate values forever"
223
223
In the examples above we generated finite sequences, but we can also make a generator that yields values forever. For instance, an unending sequence of pseudo-random numbers.
224
224
225
-
That surely would require a `break` (or `return`) in `for..of` over such generator, otherwise the loop would repeat forever and hang.
225
+
That surely would require a `break` (or `return`) in `for..of` over such generator. Otherwise, the loop would repeat forever and hang.
Now we'd like to reuse it for generation of a more complex sequence:
240
+
Now we'd like to reuse it to generate a more complex sequence:
241
241
- first, digits `0..9` (with character codes 48..57),
242
242
- followed by uppercase alphabet letters `A..Z` (character codes 65..90)
243
243
- followed by lowercase alphabet letters `a..z` (character codes 97..122)
@@ -316,7 +316,7 @@ A generator composition is a natural way to insert a flow of one generator into
316
316
317
317
## "yield" is a two-way road
318
318
319
-
Till this moment, generators were similar to iterable objects, with a special syntax to generate values. But in fact they are much more powerful and flexible.
319
+
Until this moment, generators were similar to iterable objects, with a special syntax to generate values. But in fact they are much more powerful and flexible.
320
320
321
321
That's because `yield` is a two-way road: it not only returns the result outside, but also can pass the value inside the generator.
322
322
@@ -422,7 +422,7 @@ generator.throw(new Error("The answer is not found in my database")); // (2)
422
422
*/!*
423
423
```
424
424
425
-
The error, thrown into the generator at the line `(2)` leads to an exception in the line `(1)` with `yield`. In the example above, `try..catch` catches it and shows.
425
+
The error, thrown into the generator at line `(2)` leads to an exception in line `(1)` with `yield`. In the example above, `try..catch` catches it and shows it.
426
426
427
427
If we don't catch it, then just like any exception, it "falls out" the generator into the calling code.
428
428
@@ -456,6 +456,6 @@ If we don't catch the error there, then, as usual, it falls through to the outer
456
456
457
457
In modern JavaScript, generators are rarely used. But sometimes they come in handy, because the ability of a function to exchange data with the calling code during the execution is quite unique. And, surely, they are great for making iterable objects.
458
458
459
-
Also, in the next chapter we'll learn async generators, which are used to read streams of asynchronously generated data (e.g paginated fetches over a network) in `for await ... of`loop.
459
+
Also, in the next chapter we'll learn async generators, which are used to read streams of asynchronously generated data (e.g paginated fetches over a network) in `for await ... of`loops.
460
460
461
461
In web-programming we often work with streamed data, so that's another very important use case.
0 commit comments