Skip to content

Commit b936cae

Browse files
author
mean2me
committed
WIP: first part of Async iterators and generators
1 parent 2a9445d commit b936cae

File tree

1 file changed

+65
-61
lines changed
  • 1-js/12-generators-iterators/2-async-iterators-generators

1 file changed

+65
-61
lines changed

1-js/12-generators-iterators/2-async-iterators-generators/article.md

Lines changed: 65 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,35 @@
1+
# Iteratori e generatori asincroni
12

2-
# Async iterators and generators
3+
Gli iteratori asincroni consentono di iterare su dati che arrivano in modo asincrono, a richiesta. Per esempio, quando eseguiamo una serie di download parziali dalla rete. I generatori asincroni ci consentono di semplificare questo processo.
34

4-
Asynchronous iterators allow to iterate over data that comes asynchronously, on-demand. For instance, when we download something chunk-by-chunk over a network. Asynchronous generators make it even more convenient.
5+
Vediamo prima un semplice esempio per prendere confidenza con la sintassi, dopodiché analizzeremo un caso d'uso reale.
56

6-
Let's see a simple example first, to grasp the syntax, and then review a real-life use case.
7+
## Iteratori asincroni
78

8-
## Async iterators
9+
Gli iteratori asincroni sono simili ai comuni iteratori, con alcune differenze sintattiche.
910

10-
Asynchronous iterators are similar to regular iterators, with a few syntactic differences.
11-
12-
"Regular" iterable object, as described in the chapter <info:iterable>, look like this:
11+
Gli oggetti iteratori "comuni", come abbiamo detto nel capitolo <info:iterable>, si presentano in questo modo:
1312

1413
```js run
1514
let range = {
1615
from: 1,
1716
to: 5,
1817

19-
// for..of calls this method once in the very beginning
18+
// for..of invoca questo metodo una sola volta all'inizio dell'esecuzione
2019
*!*
2120
[Symbol.iterator]() {
2221
*/!*
23-
// ...it returns the iterator object:
24-
// onward, for await..of works only with that object,
25-
// asking it for next values using next()
22+
// ...ritorna l'oggetto iteratore:
23+
// dopodich&eacute;, for..of interagisce solo con questo oggetto,
24+
// chiedendogli i valori successivi tramite il metodo next()
2625
return {
2726
current: this.from,
2827
last: this.to,
2928

30-
// next() is called on each iteration by the for..of loop
29+
// next() viene invocato ad ogni iterazione dal ciclo for..of
3130
*!*
3231
next() { // (2)
33-
// it should return the value as an object {done:.., value :...}
32+
// dovrebbe ritornare il valore come un oggetto {done:.., value:..}
3433
*/!*
3534
if (this.current <= this.last) {
3635
return { done: false, value: this.current++ };
@@ -43,43 +42,44 @@ let range = {
4342
};
4443

4544
for(let value of range) {
46-
alert(value); // 1 then 2, then 3, then 4, then 5
45+
alert(value); // 1 poi 2, poi 3, poi 4, poi 5
4746
}
4847
```
4948

50-
If necessary, please refer to the [chapter about iterables](info:iterable) for details about regular iterators.
49+
Se necessario, rileggersi il [capitolo sugli iteratori](info:iterable) per avere maggiori dettagli circa gli iteratori comuni.
50+
51+
Per rendere l'oggetto iteratore asincrono:
5152

52-
To make the object iterable asynchronously:
53-
1. We need to use `Symbol.asyncIterator` instead of `Symbol.iterator`.
54-
2. `next()` should return a promise.
55-
3. To iterate over such an object, we should use `for await (let item of iterable)` loop.
53+
1. Dobbiamo usare `Symbol.asyncIterator` anzich&eacute; `Symbol.iterator`.
54+
2. `next()` dovrebbe ritornare una promise.
55+
3. Per iterare sui valori di tale oggetto, dobbiamo usare un ciclo del tipo: `for await (let item of iterable)`.
5656

57-
Let's make an iterable `range` object, like the one before, but now it will return values asynchronously, one per second:
57+
Rendiamo l'oggetto `range` iterabile, come nell'esempio precedente ma, questa volta, ritorner&agrave; i valori in modo asincrono, uno ogni secondo:
5858

5959
```js run
6060
let range = {
6161
from: 1,
6262
to: 5,
6363

64-
// for await..of calls this method once in the very beginning
64+
// for await..of invoca questo metodo una sola volta all'inizio dell'esecuzione
6565
*!*
6666
[Symbol.asyncIterator]() { // (1)
6767
*/!*
68-
// ...it returns the iterator object:
69-
// onward, for await..of works only with that object,
70-
// asking it for next values using next()
68+
// ...ritorna l'oggetto iteratore:
69+
// dopodich&egrave;, for await..of interagisce solo con questo oggetto,
70+
// chiedendogli i valori successivi tramite il metodo next()
7171
return {
7272
current: this.from,
7373
last: this.to,
7474

75-
// next() is called on each iteration by the for..of loop
75+
// next() viene invocato ad ogni iterazione dal ciclo for await..of
7676
*!*
7777
async next() { // (2)
78-
// it should return the value as an object {done:.., value :...}
79-
// (automatically wrapped into a promise by async)
78+
// dovrebbe ritornare il valore come un oggetto {done:.., value:..}
79+
// (automaticamente racchiuso in una promise dal momento che siamo un metodo 'async')
8080
*/!*
8181

82-
// can use await inside, do async stuff:
82+
// possiamo utilizzare await all'interno per eseguire codice asincrono:
8383
await new Promise(resolve => setTimeout(resolve, 1000)); // (3)
8484

8585
if (this.current <= this.last) {
@@ -103,38 +103,40 @@ let range = {
103103
})()
104104
```
105105

106-
As we can see, the structure is similar to regular iterators:
106+
Possiamo notare che la struttura &egrave; simile a quella dei comuni iteratori:
107107

108-
1. To make an object asynchronously iterable, it must have a method `Symbol.asyncIterator` `(1)`.
109-
2. This method must return the object with `next()` method returning a promise `(2)`.
110-
3. The `next()` method doesn't have to be `async`, it may be a regular method returning a promise, but `async` allows to use `await`, so that's convenient. Here we just delay for a second `(3)`.
111-
4. To iterate, we use `for await(let value of range)` `(4)`, namely add "await" after "for". It calls `range[Symbol.asyncIterator]()` once, and then its `next()` for values.
108+
1. Per rendere un oggetto iterabile in modo asincrono, esso deve contenere un metodo `Symbol.asyncIterator` `(1)`.
109+
2. Questo metodo deve ritornare un oggetto contenente il metodo `next()`, che ritorna a sua volta una promise `(2)`.
110+
3. Il metodo `next()` non deve necessariamente essere `async`; pu&ograve; essere un metodo normale che ritorna una promise, anche se `async` ci
111+
consentirebbe di utilizzare `await`, che pu&ograve; tornarci utile. Nell'esempio, abbiamo utilizzato un ritardo di un secondo `(3)`.
112+
4. Per iterare dobbiamo utilizzare il ciclo `for await(let value of range)` `(4)`, si tratta di aggiungere "await" dopo il "for". Questo ciclo invoca il metodo `range[Symbol.asyncIterator]()` una sola volta, dopodich&eacute; il metodo invocher&agrave; `next()` per ottenere i valori.
112113

113-
Here's a small cheatsheet:
114+
Ecco una semplice tabella di riepilogo:
114115

115-
| | Iterators | Async iterators |
116-
|-------|-----------|-----------------|
117-
| Object method to provide iterator | `Symbol.iterator` | `Symbol.asyncIterator` |
118-
| `next()` return value is | any value | `Promise` |
119-
| to loop, use | `for..of` | `for await..of` |
116+
| | Iteratori | Iteratori asincroni |
117+
| ----------------------------------------------- | ----------------- | ---------------------- |
118+
| Metodo dell'oggetto che restituisce l'iteratore | `Symbol.iterator` | `Symbol.asyncIterator` |
119+
| Il valore ritornato da `next()` &egrave; | qualsiasi valore | `Promise` |
120+
| ciclo da utilizzare | `for..of` | `for await..of` |
120121

122+
````warn header="Lo spread operator `...` non funziona in modo asincrono"
123+
Le funzionalit&agrave; offerte dai comuni iteratori (sincroni) non sono disponibili per gli iteratori asincroni.
121124

122-
````warn header="The spread operator `...` doesn't work asynchronously"
123-
Features that require regular, synchronous iterators, don't work with asynchronous ones.
125+
Per esempio, lo spread operator non pu&agrave; essere utilizzato:
124126

125-
For instance, a spread operator won't work:
126127
```js
127-
alert( [...range] ); // Error, no Symbol.iterator
128+
alert([...range]); // Errore, non c'&agrave; Symbol.iterator
128129
```
129130

130-
That's natural, as it expects to find `Symbol.iterator`, same as `for..of` without `await`. Not `Symbol.asyncIterator`.
131+
Questo &egrave; prevedibile, dal momento che lo spread operator ha bisogno di `Symbol.iterator` anzich&eacute; `Symbol.asyncIterator`. Lo stesso vale per `for..of` (senza `await`).
132+
131133
````
132134
133-
## Async generators
135+
## Generatori asincroni
134136
135-
As we already know, JavaScript also supports generators, and they are iterable.
137+
Come gi&agrave; sappiamo, JavaScript supporta anche i cosiddetti generatori, che sono anche iteratori.
136138
137-
Let's recall a sequence generator from the chapter [](info:generators). It generates a sequence of values from `start` to `end`:
139+
Ricordiamo l'esempio del generatore di una sequenza di numeri da `start` a `end`, nel capitolo [](info:generators):
138140
139141
```js run
140142
function* generateSequence(start, end) {
@@ -144,15 +146,15 @@ function* generateSequence(start, end) {
144146
}
145147
146148
for(let value of generateSequence(1, 5)) {
147-
alert(value); // 1, then 2, then 3, then 4, then 5
149+
alert(value); // 1, poi 2, poi 3, poi 4, poi 5
148150
}
149151
```
150152
151-
In regular generators we can't use `await`. All values must come synchronously: there's no place for delay in `for..of`, it's a synchronous construct.
153+
Nei normali generatori non possiamo usare `await`. Tutti i valori devono essere ritornati in modo sincrono: non c'&egrave; modo di ritornare valori "futuri" utilizzando il ciclo `for..of`, dal momento che si tratta di un costrutto di tipo sincrono.
152154
153-
But what if we need to use `await` in the generator body? To perform network requests, for instance.
155+
Cosa fare se avessimo bisogno di usare `await` all'interno di un generatore? Per eseguire, ad esempio, una richiesta dalla rete?
154156
155-
No problem, just prepend it with `async`, like this:
157+
Non c'&egrave; problema, sar&agrave; sufficiente anteporre la parola chiave `async`, come nell'esempio seguente:
156158
157159
```js run
158160
*!*async*/!* function* generateSequence(start, end) {
@@ -173,41 +175,42 @@ No problem, just prepend it with `async`, like this:
173175
174176
let generator = generateSequence(1, 5);
175177
for *!*await*/!* (let value of generator) {
176-
alert(value); // 1, then 2, then 3, then 4, then 5
178+
alert(value); // 1, poi 2, poi 3, poi 4, poi 5
177179
}
178180
179181
})();
180182
```
181183
182-
Now we have the async generator, iterable with `for await...of`.
184+
In questo modo abbiamo ottenuto il generatore asincrono, che possiamo usare nelle iterazioni con il ciclo `for await..of`.
183185
184-
It's indeed very simple. We add the `async` keyword, and the generator now can use `await` inside of it, rely on promises and other async functions.
186+
E' molto semplice. Aggiungiamo la parola chiave `async` ed ecco che il generatore pu&ograve; utilizzare `await` al suo interno e trarre vantaggio delle promise, cos&igrave; come di tutte le altre funzioni asincrone.
185187
186-
Technically, another the difference of an async generator is that its `generator.next()` method is now asynchronous also, it returns promises.
188+
Tecnicamente, un'altra importante caratteristica dei generatori asincroni &egrave; che anche il relativo metodo `generator.next()` diventa asincrono, ritornando delle promise.
187189
188-
In a regular generator we'd use `result = generator.next()` to get values. In an async generator, we should add `await`, like this:
190+
Con un generatore normale utilizzeremmo `result = generator.next()` per ottenere i valori ritornati. Con i generatori asincroni dobbiamo, invece, aggiungere `await`, come nell'esempio:
189191
190192
```js
191193
result = await generator.next(); // result = {value: ..., done: true/false}
192194
```
193195
194-
## Async iterables
196+
## Iteratori asincroni
195197
196-
As we already know, to make an object iterable, we should add `Symbol.iterator` to it.
198+
Come gi&agrave; sappiamo, per rendere un semplice oggetto un oggetto iteratore, dobbiamo aggiungere il metodo `Symbol.iterator`:
197199
198200
```js
199201
let range = {
200202
from: 1,
201203
to: 5,
202204
*!*
203205
[Symbol.iterator]() {
204-
return <object with next to make range iterable>
206+
return <oggetto che abbia un metodo next() per trasformare l'oggetto in un iteratore>
205207
}
206208
*/!*
207209
}
208210
```
209211
210212
A common practice for `Symbol.iterator` is to return a generator, rather than a plain object with `next` as in the example before.
213+
Un approccio comune &egrave; quello di far ritornare a `Symbol.iterator` un generatore anzich&eacute; un normale oggetto con il metodo `next`, come nell'esempio precedente.
211214
212215
Let's recall an example from the chapter [](info:generators):
213216
@@ -242,7 +245,7 @@ let range = {
242245
*/!*
243246
for(let value = this.from; value <= this.to; value++) {
244247
245-
// make a pause between values, wait for something
248+
// make a pause between values, wait for something
246249
await new Promise(resolve => setTimeout(resolve, 1000));
247250
248251
yield value;
@@ -361,4 +364,5 @@ In web-development we often meet streams of data, when it flows chunk-by-chunk.
361364
362365
We can use async generators to process such data, but it's also worth to mention that there's also another API called Streams, that provides special interfaces to work with such streams, to transform the data and to pass it from one stream to another (e.g. download from one place and immediately send elsewhere).
363366
364-
Streams API is not a part of JavaScript language standard.
367+
Streams API is not a part of JavaScript language standard.
368+
````

0 commit comments

Comments
 (0)