SlideShare a Scribd company logo
1 of 178
Download to read offline
Reiterating
JavaScript &
Node.js iterators
Luciano Mammino ( )
@loige
loige.link/iter RomaJS - June 16, 2021
1
@loige
loige.link/iter 2
How many ways do you
know to "do iteration" in
JavaScript & Node.js? 😰
@loige
3
for i / for...in / for...of
@loige
4
while / do while
@loige
5
Array.forEach / Array.map / Array.flatMap
/ Array.reduce / Array.reduceRight  /
Array.filter / Array.find /
Array.findIndex / Array.entries /
Array.values / Array.every / Array.some
@loige
6
Object.keys / Object.values /
Object.entries
@loige
7
Iterators / Generators
@loige
8
Spread operator
[...iterable]
@loige
9
Events / Streams
@loige
10
Async iterators / Async generators
@loige
11
for await...of
@loige
12
That was 28 different concepts! 😳
@loige
13
📝AGENDA
Iteration protocols... What? Why?
Syntax review
Iteration protocols
Iterator protocol
Iterable protocol
Generator functions
Async iterator protocol
Async iterable protocol
Tips & tricks
@loige
14
Let me introduce myself...
@loige
15
Let me introduce myself...
I'm Luciano ( 🍕🍝) 👋
@loige
15
Let me introduce myself...
I'm Luciano ( 🍕🍝) 👋
 Senior Architect
@loige
15
Let me introduce myself...
I'm Luciano ( 🍕🍝) 👋
 Senior Architect
nodejsdp.link
Co-Author of Node.js Design Patterns  👉
@loige
15
Let me introduce myself...
I'm Luciano ( 🍕🍝) 👋
 Senior Architect
nodejsdp.link
Co-Author of Node.js Design Patterns  👉
Connect with me:
 
  (blog)
  (twitter)
  (twitch)
  (github)
loige.co
@loige
loige
lmammino
@loige
15
We are business focused
technologists that deliver.
 |  |
Accelerated Serverless AI as a Service Platform Modernisation
WE ARE HIRING: Do you want to ?
work with us
@loige 16
Iteration protocols
what? why? 🤔
@loige
An attempt at standardizing "iteration" behaviors
providing a consistent and interoperable API
Use for...of, for await...of and spread operator.
You can also create lazy iterators
You can also deal with async iteration
You can create your own custom iterators/iterables
17
Syntax Review 🧐
@loige
18
const judokas = [
'Driulis Gonzalez Morales',
'Ilias Iliadis',
'Tadahiro Nomura',
'Anton Geesink',
'Teddy Riner',
'Ryoko Tani'
]
for (const judoka of judokas) {
console.log(judoka)
}
1
2
3
4
5
6
7
8
9
10
11
12
@loige
for...of
19
const judokas = [
'Driulis Gonzalez Morales',
'Ilias Iliadis',
'Tadahiro Nomura',
'Anton Geesink',
'Teddy Riner',
'Ryoko Tani'
]
for (const judoka of judokas) {
console.log(judoka)
}
1
2
3
4
5
6
7
8
9
10
11
12
const judokas = [
'Driulis Gonzalez Morales',
'Ilias Iliadis',
'Tadahiro Nomura',
'Anton Geesink',
'Teddy Riner',
'Ryoko Tani'
]
1
2
3
4
5
6
7
8
9
for (const judoka of judokas) {
10
console.log(judoka)
11
}
12
@loige
for...of
Driulis Gonzalez Morales
Ilias Iliadis
Tadahiro Nomura
Anton Geesink
Teddy Riner
Ryoko Tani
OUTPUT
19
const judokas = [
'Driulis Gonzalez Morales',
'Ilias Iliadis',
'Tadahiro Nomura',
'Anton Geesink',
'Teddy Riner',
'Ryoko Tani'
]
for (const judoka of judokas) {
console.log(judoka)
}
1
2
3
4
5
6
7
8
9
10
11
12
const judokas = [
'Driulis Gonzalez Morales',
'Ilias Iliadis',
'Tadahiro Nomura',
'Anton Geesink',
'Teddy Riner',
'Ryoko Tani'
]
1
2
3
4
5
6
7
8
9
for (const judoka of judokas) {
10
console.log(judoka)
11
}
12
for (const judoka of judokas) {
}
const judokas = [
1
'Driulis Gonzalez Morales',
2
'Ilias Iliadis',
3
'Tadahiro Nomura',
4
'Anton Geesink',
5
'Teddy Riner',
6
'Ryoko Tani'
7
]
8
9
10
console.log(judoka)
11
12
@loige
for...of
Driulis Gonzalez Morales
Ilias Iliadis
Tadahiro Nomura
Anton Geesink
Teddy Riner
Ryoko Tani
OUTPUT
19
const judokas = [
'Driulis Gonzalez Morales',
'Ilias Iliadis',
'Tadahiro Nomura',
'Anton Geesink',
'Teddy Riner',
'Ryoko Tani'
]
for (const judoka of judokas) {
console.log(judoka)
}
1
2
3
4
5
6
7
8
9
10
11
12
const judokas = [
'Driulis Gonzalez Morales',
'Ilias Iliadis',
'Tadahiro Nomura',
'Anton Geesink',
'Teddy Riner',
'Ryoko Tani'
]
1
2
3
4
5
6
7
8
9
for (const judoka of judokas) {
10
console.log(judoka)
11
}
12
for (const judoka of judokas) {
}
const judokas = [
1
'Driulis Gonzalez Morales',
2
'Ilias Iliadis',
3
'Tadahiro Nomura',
4
'Anton Geesink',
5
'Teddy Riner',
6
'Ryoko Tani'
7
]
8
9
10
console.log(judoka)
11
12
console.log(judoka)
const judokas = [
1
'Driulis Gonzalez Morales',
2
'Ilias Iliadis',
3
'Tadahiro Nomura',
4
'Anton Geesink',
5
'Teddy Riner',
6
'Ryoko Tani'
7
]
8
9
for (const judoka of judokas) {
10
11
}
12
@loige
for...of
Driulis Gonzalez Morales
Ilias Iliadis
Tadahiro Nomura
Anton Geesink
Teddy Riner
Ryoko Tani
OUTPUT
19
const judokas = [
'Driulis Gonzalez Morales',
'Ilias Iliadis',
'Tadahiro Nomura',
'Anton Geesink',
'Teddy Riner',
'Ryoko Tani'
]
for (const judoka of judokas) {
console.log(judoka)
}
1
2
3
4
5
6
7
8
9
10
11
12
const judokas = [
'Driulis Gonzalez Morales',
'Ilias Iliadis',
'Tadahiro Nomura',
'Anton Geesink',
'Teddy Riner',
'Ryoko Tani'
]
1
2
3
4
5
6
7
8
9
for (const judoka of judokas) {
10
console.log(judoka)
11
}
12
for (const judoka of judokas) {
}
const judokas = [
1
'Driulis Gonzalez Morales',
2
'Ilias Iliadis',
3
'Tadahiro Nomura',
4
'Anton Geesink',
5
'Teddy Riner',
6
'Ryoko Tani'
7
]
8
9
10
console.log(judoka)
11
12
console.log(judoka)
const judokas = [
1
'Driulis Gonzalez Morales',
2
'Ilias Iliadis',
3
'Tadahiro Nomura',
4
'Anton Geesink',
5
'Teddy Riner',
6
'Ryoko Tani'
7
]
8
9
for (const judoka of judokas) {
10
11
}
12
const judokas = [
'Driulis Gonzalez Morales',
'Ilias Iliadis',
'Tadahiro Nomura',
'Anton Geesink',
'Teddy Riner',
'Ryoko Tani'
]
for (const judoka of judokas) {
console.log(judoka)
}
1
2
3
4
5
6
7
8
9
10
11
12
@loige
for...of
Driulis Gonzalez Morales
Ilias Iliadis
Tadahiro Nomura
Anton Geesink
Teddy Riner
Ryoko Tani
OUTPUT
19
const judoka = 'Ryoko Tani'
for (const char of judoka) {
console.log(char)
}
1
2
3
4
5
@loige
for...of (with strings)
20
const judoka = 'Ryoko Tani'
for (const char of judoka) {
console.log(char)
}
1
2
3
4
5
@loige
for...of (with strings)
R
y
o
k
o
T
a
n
i
OUTPUT
20
const medals = new Set([
'gold',
'silver',
'bronze'
])
for (const medal of medals) {
console.log(medal)
}
1
2
3
4
5
6
7
8
9
@loige
for...of (with Set)
21
const medals = new Set([
'gold',
'silver',
'bronze'
])
for (const medal of medals) {
console.log(medal)
}
1
2
3
4
5
6
7
8
9
@loige
for...of (with Set)
 
gold
silver
bronze
OUTPUT
21
const medallists = new Map([
['Teddy Riner', 33],
['Driulis Gonzalez Morales', 16],
['Ryoko Tani', 16],
['Ilias Iliadis', 15]
])
for (const [judoka, medals] of medallists) {
console.log(`${judoka} has won ${medals} medals`)
}
1
2
3
4
5
6
7
8
9
10
@loige
for...of (with Map)
22
const medallists = new Map([
['Teddy Riner', 33],
['Driulis Gonzalez Morales', 16],
['Ryoko Tani', 16],
['Ilias Iliadis', 15]
])
for (const [judoka, medals] of medallists) {
console.log(`${judoka} has won ${medals} medals`)
}
1
2
3
4
5
6
7
8
9
10
@loige
for...of (with Map)
Teddy Riner has won 33 medals
Driulis Gonzalez Morales has won 16 medals
Ryoko Tani has won 16 medals
Ilias Iliadis has won 15 medals
OUTPUT
22
const medallists = {
'Teddy Riner': 33,
'Driulis Gonzalez Morales': 16,
'Ryoko Tani': 16,
'Ilias Iliadis': 15
}
for (const [judoka, medals] of Object.entries(medallists))
console.log(`${judoka} has won ${medals} medals`)
}
1
2
3
4
5
6
7
8
9
10
@loige
for...of (with object & Object.entries)
23
const medallists = {
'Teddy Riner': 33,
'Driulis Gonzalez Morales': 16,
'Ryoko Tani': 16,
'Ilias Iliadis': 15
}
for (const [judoka, medals] of Object.entries(medallists))
console.log(`${judoka} has won ${medals} medals`)
}
1
2
3
4
5
6
7
8
9
10
@loige
for...of (with object & Object.entries)
Teddy Riner has won 33 medals
Driulis Gonzalez Morales has won 16 medals
Ryoko Tani has won 16 medals
Ilias Iliadis has won 15 medals
OUTPUT
23
const medallists = {
'Teddy Riner': 33,
'Driulis Gonzalez Morales': 16,
'Ryoko Tani': 16,
'Ilias Iliadis': 15
}
for (const [judoka, medals] of medallists) {
console.log(`${judoka} has won ${medals} medals`)
}
1
2
3
4
5
6
7
8
9
10
@loige
for...of (with object literals)
24
const medallists = {
'Teddy Riner': 33,
'Driulis Gonzalez Morales': 16,
'Ryoko Tani': 16,
'Ilias Iliadis': 15
}
for (const [judoka, medals] of medallists) {
console.log(`${judoka} has won ${medals} medals`)
}
1
2
3
4
5
6
7
8
9
10
@loige
for...of (with object literals)
for (const [judoka, medals] of medallists) {
^
TypeError: medallists is not iterable
at Object. (.../05-for-of-object.js:8:32)
ERROR
24
const countdown = [3, 2, 1, 0]
// spread into array
const from5to0 = [5, 4, ...countdown]
console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ]
// spread function arguments
console.log('countdown data:', ...countdown)
// countdown data: 3 2 1 0
1
2
3
4
5
6
7
8
9
@loige
Spread operator
25
const countdown = [3, 2, 1, 0]
// spread into array
const from5to0 = [5, 4, ...countdown]
console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ]
// spread function arguments
console.log('countdown data:', ...countdown)
// countdown data: 3 2 1 0
1
2
3
4
5
6
7
8
9
const countdown = [3, 2, 1, 0]
1
2
// spread into array
3
const from5to0 = [5, 4, ...countdown]
4
console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ]
5
6
// spread function arguments
7
console.log('countdown data:', ...countdown)
8
// countdown data: 3 2 1 0
9
@loige
Spread operator
25
const countdown = [3, 2, 1, 0]
// spread into array
const from5to0 = [5, 4, ...countdown]
console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ]
// spread function arguments
console.log('countdown data:', ...countdown)
// countdown data: 3 2 1 0
1
2
3
4
5
6
7
8
9
const countdown = [3, 2, 1, 0]
1
2
// spread into array
3
const from5to0 = [5, 4, ...countdown]
4
console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ]
5
6
// spread function arguments
7
console.log('countdown data:', ...countdown)
8
// countdown data: 3 2 1 0
9
// spread into array
const from5to0 = [5, 4, ...countdown]
console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ]
const countdown = [3, 2, 1, 0]
1
2
3
4
5
6
// spread function arguments
7
console.log('countdown data:', ...countdown)
8
// countdown data: 3 2 1 0
9
@loige
Spread operator
25
const countdown = [3, 2, 1, 0]
// spread into array
const from5to0 = [5, 4, ...countdown]
console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ]
// spread function arguments
console.log('countdown data:', ...countdown)
// countdown data: 3 2 1 0
1
2
3
4
5
6
7
8
9
const countdown = [3, 2, 1, 0]
1
2
// spread into array
3
const from5to0 = [5, 4, ...countdown]
4
console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ]
5
6
// spread function arguments
7
console.log('countdown data:', ...countdown)
8
// countdown data: 3 2 1 0
9
// spread into array
const from5to0 = [5, 4, ...countdown]
console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ]
const countdown = [3, 2, 1, 0]
1
2
3
4
5
6
// spread function arguments
7
console.log('countdown data:', ...countdown)
8
// countdown data: 3 2 1 0
9
// spread function arguments
console.log('countdown data:', ...countdown)
// countdown data: 3 2 1 0
const countdown = [3, 2, 1, 0]
1
2
// spread into array
3
const from5to0 = [5, 4, ...countdown]
4
console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ]
5
6
7
8
9
@loige
Spread operator
25
const countdown = [3, 2, 1, 0]
// spread into array
const from5to0 = [5, 4, ...countdown]
console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ]
// spread function arguments
console.log('countdown data:', ...countdown)
// countdown data: 3 2 1 0
1
2
3
4
5
6
7
8
9
const countdown = [3, 2, 1, 0]
1
2
// spread into array
3
const from5to0 = [5, 4, ...countdown]
4
console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ]
5
6
// spread function arguments
7
console.log('countdown data:', ...countdown)
8
// countdown data: 3 2 1 0
9
// spread into array
const from5to0 = [5, 4, ...countdown]
console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ]
const countdown = [3, 2, 1, 0]
1
2
3
4
5
6
// spread function arguments
7
console.log('countdown data:', ...countdown)
8
// countdown data: 3 2 1 0
9
// spread function arguments
console.log('countdown data:', ...countdown)
// countdown data: 3 2 1 0
const countdown = [3, 2, 1, 0]
1
2
// spread into array
3
const from5to0 = [5, 4, ...countdown]
4
console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ]
5
6
7
8
9
const countdown = [3, 2, 1, 0]
// spread into array
const from5to0 = [5, 4, ...countdown]
console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ]
// spread function arguments
console.log('countdown data:', ...countdown)
// countdown data: 3 2 1 0
1
2
3
4
5
6
7
8
9
@loige
Spread operator
25
import {
DynamoDBClient,
paginateListTables
} from '@aws-sdk/client-dynamodb'
const client = new DynamoDBClient({});
for await (const page of paginateListTables({ client }, {})) {
// page.TableNames is an array of table names
for (const tableName of page.TableNames) {
console.log(tableName)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
@loige
for await...of (async iterable)
26
import {
DynamoDBClient,
paginateListTables
} from '@aws-sdk/client-dynamodb'
const client = new DynamoDBClient({});
for await (const page of paginateListTables({ client }, {})) {
// page.TableNames is an array of table names
for (const tableName of page.TableNames) {
console.log(tableName)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
import {
DynamoDBClient,
paginateListTables
} from '@aws-sdk/client-dynamodb'
1
2
3
4
5
const client = new DynamoDBClient({});
6
7
for await (const page of paginateListTables({ client }, {})) {
8
// page.TableNames is an array of table names
9
for (const tableName of page.TableNames) {
10
console.log(tableName)
11
}
12
}
13
@loige
for await...of (async iterable)
26
import {
DynamoDBClient,
paginateListTables
} from '@aws-sdk/client-dynamodb'
const client = new DynamoDBClient({});
for await (const page of paginateListTables({ client }, {})) {
// page.TableNames is an array of table names
for (const tableName of page.TableNames) {
console.log(tableName)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
import {
DynamoDBClient,
paginateListTables
} from '@aws-sdk/client-dynamodb'
1
2
3
4
5
const client = new DynamoDBClient({});
6
7
for await (const page of paginateListTables({ client }, {})) {
8
// page.TableNames is an array of table names
9
for (const tableName of page.TableNames) {
10
console.log(tableName)
11
}
12
}
13
const client = new DynamoDBClient({});
import {
1
DynamoDBClient,
2
paginateListTables
3
} from '@aws-sdk/client-dynamodb'
4
5
6
7
for await (const page of paginateListTables({ client }, {})) {
8
// page.TableNames is an array of table names
9
for (const tableName of page.TableNames) {
10
console.log(tableName)
11
}
12
}
13
@loige
for await...of (async iterable)
26
import {
DynamoDBClient,
paginateListTables
} from '@aws-sdk/client-dynamodb'
const client = new DynamoDBClient({});
for await (const page of paginateListTables({ client }, {})) {
// page.TableNames is an array of table names
for (const tableName of page.TableNames) {
console.log(tableName)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
import {
DynamoDBClient,
paginateListTables
} from '@aws-sdk/client-dynamodb'
1
2
3
4
5
const client = new DynamoDBClient({});
6
7
for await (const page of paginateListTables({ client }, {})) {
8
// page.TableNames is an array of table names
9
for (const tableName of page.TableNames) {
10
console.log(tableName)
11
}
12
}
13
const client = new DynamoDBClient({});
import {
1
DynamoDBClient,
2
paginateListTables
3
} from '@aws-sdk/client-dynamodb'
4
5
6
7
for await (const page of paginateListTables({ client }, {})) {
8
// page.TableNames is an array of table names
9
for (const tableName of page.TableNames) {
10
console.log(tableName)
11
}
12
}
13
for await (const page of paginateListTables({ client }, {})) {
}
import {
1
DynamoDBClient,
2
paginateListTables
3
} from '@aws-sdk/client-dynamodb'
4
5
const client = new DynamoDBClient({});
6
7
8
// page.TableNames is an array of table names
9
for (const tableName of page.TableNames) {
10
console.log(tableName)
11
}
12
13
@loige
for await...of (async iterable)
26
import {
DynamoDBClient,
paginateListTables
} from '@aws-sdk/client-dynamodb'
const client = new DynamoDBClient({});
for await (const page of paginateListTables({ client }, {})) {
// page.TableNames is an array of table names
for (const tableName of page.TableNames) {
console.log(tableName)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
import {
DynamoDBClient,
paginateListTables
} from '@aws-sdk/client-dynamodb'
1
2
3
4
5
const client = new DynamoDBClient({});
6
7
for await (const page of paginateListTables({ client }, {})) {
8
// page.TableNames is an array of table names
9
for (const tableName of page.TableNames) {
10
console.log(tableName)
11
}
12
}
13
const client = new DynamoDBClient({});
import {
1
DynamoDBClient,
2
paginateListTables
3
} from '@aws-sdk/client-dynamodb'
4
5
6
7
for await (const page of paginateListTables({ client }, {})) {
8
// page.TableNames is an array of table names
9
for (const tableName of page.TableNames) {
10
console.log(tableName)
11
}
12
}
13
for await (const page of paginateListTables({ client }, {})) {
}
import {
1
DynamoDBClient,
2
paginateListTables
3
} from '@aws-sdk/client-dynamodb'
4
5
const client = new DynamoDBClient({});
6
7
8
// page.TableNames is an array of table names
9
for (const tableName of page.TableNames) {
10
console.log(tableName)
11
}
12
13
// page.TableNames is an array of table names
for (const tableName of page.TableNames) {
console.log(tableName)
}
import {
1
DynamoDBClient,
2
paginateListTables
3
} from '@aws-sdk/client-dynamodb'
4
5
const client = new DynamoDBClient({});
6
7
for await (const page of paginateListTables({ client }, {})) {
8
9
10
11
12
}
13
@loige
for await...of (async iterable)
26
import {
DynamoDBClient,
paginateListTables
} from '@aws-sdk/client-dynamodb'
const client = new DynamoDBClient({});
for await (const page of paginateListTables({ client }, {})) {
// page.TableNames is an array of table names
for (const tableName of page.TableNames) {
console.log(tableName)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
import {
DynamoDBClient,
paginateListTables
} from '@aws-sdk/client-dynamodb'
1
2
3
4
5
const client = new DynamoDBClient({});
6
7
for await (const page of paginateListTables({ client }, {})) {
8
// page.TableNames is an array of table names
9
for (const tableName of page.TableNames) {
10
console.log(tableName)
11
}
12
}
13
const client = new DynamoDBClient({});
import {
1
DynamoDBClient,
2
paginateListTables
3
} from '@aws-sdk/client-dynamodb'
4
5
6
7
for await (const page of paginateListTables({ client }, {})) {
8
// page.TableNames is an array of table names
9
for (const tableName of page.TableNames) {
10
console.log(tableName)
11
}
12
}
13
for await (const page of paginateListTables({ client }, {})) {
}
import {
1
DynamoDBClient,
2
paginateListTables
3
} from '@aws-sdk/client-dynamodb'
4
5
const client = new DynamoDBClient({});
6
7
8
// page.TableNames is an array of table names
9
for (const tableName of page.TableNames) {
10
console.log(tableName)
11
}
12
13
// page.TableNames is an array of table names
for (const tableName of page.TableNames) {
console.log(tableName)
}
import {
1
DynamoDBClient,
2
paginateListTables
3
} from '@aws-sdk/client-dynamodb'
4
5
const client = new DynamoDBClient({});
6
7
for await (const page of paginateListTables({ client }, {})) {
8
9
10
11
12
}
13
import {
DynamoDBClient,
paginateListTables
} from '@aws-sdk/client-dynamodb'
const client = new DynamoDBClient({});
for await (const page of paginateListTables({ client }, {})) {
// page.TableNames is an array of table names
for (const tableName of page.TableNames) {
console.log(tableName)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
@loige
for await...of (async iterable)
26
Iteration Protocols 😵💫
@loige
27
Iterator protocol
In JavaScript, an object is an iterator if it has a next()
method. Every time you call it, it returns an object with the
keys done (boolean) and value.
@loige
28
function createCountdown (start) {
let nextVal = start
return {
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@loige
Countdown iterator
29
function createCountdown (start) {
let nextVal = start
return {
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function createCountdown (start) {
}
1
let nextVal = start
2
return {
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
14
@loige
Countdown iterator
const countdown = createCountdown(3)
console.log(countdown.next()) // { done: false, value: 3 }
console.log(countdown.next()) // { done: false, value: 2 }
console.log(countdown.next()) // { done: false, value: 1 }
console.log(countdown.next()) // { done: false, value: 0 }
console.log(countdown.next()) // { done: true }
29
function createCountdown (start) {
let nextVal = start
return {
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function createCountdown (start) {
}
1
let nextVal = start
2
return {
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
14
let nextVal = start
function createCountdown (start) {
1
2
return {
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
}
14
@loige
Countdown iterator
const countdown = createCountdown(3)
console.log(countdown.next()) // { done: false, value: 3 }
console.log(countdown.next()) // { done: false, value: 2 }
console.log(countdown.next()) // { done: false, value: 1 }
console.log(countdown.next()) // { done: false, value: 0 }
console.log(countdown.next()) // { done: true }
29
function createCountdown (start) {
let nextVal = start
return {
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function createCountdown (start) {
}
1
let nextVal = start
2
return {
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
14
let nextVal = start
function createCountdown (start) {
1
2
return {
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
}
14
return {
}
function createCountdown (start) {
1
let nextVal = start
2
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
13
}
14
@loige
Countdown iterator
const countdown = createCountdown(3)
console.log(countdown.next()) // { done: false, value: 3 }
console.log(countdown.next()) // { done: false, value: 2 }
console.log(countdown.next()) // { done: false, value: 1 }
console.log(countdown.next()) // { done: false, value: 0 }
console.log(countdown.next()) // { done: true }
29
function createCountdown (start) {
let nextVal = start
return {
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function createCountdown (start) {
}
1
let nextVal = start
2
return {
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
14
let nextVal = start
function createCountdown (start) {
1
2
return {
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
}
14
return {
}
function createCountdown (start) {
1
let nextVal = start
2
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
13
}
14
next () {
}
function createCountdown (start) {
1
let nextVal = start
2
return {
3
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
12
}
13
}
14
@loige
Countdown iterator
const countdown = createCountdown(3)
console.log(countdown.next()) // { done: false, value: 3 }
console.log(countdown.next()) // { done: false, value: 2 }
console.log(countdown.next()) // { done: false, value: 1 }
console.log(countdown.next()) // { done: false, value: 0 }
console.log(countdown.next()) // { done: true }
29
function createCountdown (start) {
let nextVal = start
return {
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function createCountdown (start) {
}
1
let nextVal = start
2
return {
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
14
let nextVal = start
function createCountdown (start) {
1
2
return {
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
}
14
return {
}
function createCountdown (start) {
1
let nextVal = start
2
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
13
}
14
next () {
}
function createCountdown (start) {
1
let nextVal = start
2
return {
3
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
12
}
13
}
14
if (nextVal < 0) {
return { done: true }
}
function createCountdown (start) {
1
let nextVal = start
2
return {
3
next () {
4
5
6
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
}
14
@loige
Countdown iterator
const countdown = createCountdown(3)
console.log(countdown.next()) // { done: false, value: 3 }
console.log(countdown.next()) // { done: false, value: 2 }
console.log(countdown.next()) // { done: false, value: 1 }
console.log(countdown.next()) // { done: false, value: 0 }
console.log(countdown.next()) // { done: true }
29
function createCountdown (start) {
let nextVal = start
return {
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function createCountdown (start) {
}
1
let nextVal = start
2
return {
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
14
let nextVal = start
function createCountdown (start) {
1
2
return {
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
}
14
return {
}
function createCountdown (start) {
1
let nextVal = start
2
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
13
}
14
next () {
}
function createCountdown (start) {
1
let nextVal = start
2
return {
3
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
12
}
13
}
14
if (nextVal < 0) {
return { done: true }
}
function createCountdown (start) {
1
let nextVal = start
2
return {
3
next () {
4
5
6
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
}
14
return {
done: false,
value: nextVal--
}
function createCountdown (start) {
1
let nextVal = start
2
return {
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
8
9
10
11
}
12
}
13
}
14
@loige
Countdown iterator
const countdown = createCountdown(3)
console.log(countdown.next()) // { done: false, value: 3 }
console.log(countdown.next()) // { done: false, value: 2 }
console.log(countdown.next()) // { done: false, value: 1 }
console.log(countdown.next()) // { done: false, value: 0 }
console.log(countdown.next()) // { done: true }
29
function createCountdown (start) {
let nextVal = start
return {
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function createCountdown (start) {
}
1
let nextVal = start
2
return {
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
14
let nextVal = start
function createCountdown (start) {
1
2
return {
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
}
14
return {
}
function createCountdown (start) {
1
let nextVal = start
2
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
13
}
14
next () {
}
function createCountdown (start) {
1
let nextVal = start
2
return {
3
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
return {
8
done: false,
9
value: nextVal--
10
}
11
12
}
13
}
14
if (nextVal < 0) {
return { done: true }
}
function createCountdown (start) {
1
let nextVal = start
2
return {
3
next () {
4
5
6
7
return {
8
done: false,
9
value: nextVal--
10
}
11
}
12
}
13
}
14
return {
done: false,
value: nextVal--
}
function createCountdown (start) {
1
let nextVal = start
2
return {
3
next () {
4
if (nextVal < 0) {
5
return { done: true }
6
}
7
8
9
10
11
}
12
}
13
}
14
function createCountdown (start) {
let nextVal = start
return {
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@loige
Countdown iterator
const countdown = createCountdown(3)
console.log(countdown.next()) // { done: false, value: 3 }
console.log(countdown.next()) // { done: false, value: 2 }
console.log(countdown.next()) // { done: false, value: 1 }
console.log(countdown.next()) // { done: false, value: 0 }
console.log(countdown.next()) // { done: true }
29
Iterable protocol
An object is iterable if it implements the @@iterator*
method, a zero-argument function that returns an iterator.
 
* Symbol.iterator
@loige
30
function createCountdown (start) {
let nextVal = start
return {
[Symbol.iterator]: () => ({
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
})
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@loige
Countdown iterable
31
function createCountdown (start) {
let nextVal = start
return {
[Symbol.iterator]: () => ({
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
})
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function createCountdown (start) {
}
1
let nextVal = start
2
return {
3
[Symbol.iterator]: () => ({
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
})
14
}
15
16
@loige
Countdown iterable
const countdown = createCountdown(3)
for (const value of countdown) {
console.log(value)
}
// 3
// 2
// 1
// 0
31
function createCountdown (start) {
let nextVal = start
return {
[Symbol.iterator]: () => ({
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
})
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function createCountdown (start) {
}
1
let nextVal = start
2
return {
3
[Symbol.iterator]: () => ({
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
})
14
}
15
16
let nextVal = start
function createCountdown (start) {
1
2
return {
3
[Symbol.iterator]: () => ({
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
})
14
}
15
}
16
@loige
Countdown iterable
const countdown = createCountdown(3)
for (const value of countdown) {
console.log(value)
}
// 3
// 2
// 1
// 0
31
function createCountdown (start) {
let nextVal = start
return {
[Symbol.iterator]: () => ({
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
})
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function createCountdown (start) {
}
1
let nextVal = start
2
return {
3
[Symbol.iterator]: () => ({
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
})
14
}
15
16
let nextVal = start
function createCountdown (start) {
1
2
return {
3
[Symbol.iterator]: () => ({
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
})
14
}
15
}
16
return {
}
function createCountdown (start) {
1
let nextVal = start
2
3
[Symbol.iterator]: () => ({
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
})
14
15
}
16
@loige
Countdown iterable
const countdown = createCountdown(3)
for (const value of countdown) {
console.log(value)
}
// 3
// 2
// 1
// 0
31
function createCountdown (start) {
let nextVal = start
return {
[Symbol.iterator]: () => ({
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
})
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function createCountdown (start) {
}
1
let nextVal = start
2
return {
3
[Symbol.iterator]: () => ({
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
})
14
}
15
16
let nextVal = start
function createCountdown (start) {
1
2
return {
3
[Symbol.iterator]: () => ({
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
})
14
}
15
}
16
return {
}
function createCountdown (start) {
1
let nextVal = start
2
3
[Symbol.iterator]: () => ({
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
})
14
15
}
16
[Symbol.iterator]: () => ({
})
function createCountdown (start) {
1
let nextVal = start
2
return {
3
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
14
}
15
}
16
@loige
Countdown iterable
const countdown = createCountdown(3)
for (const value of countdown) {
console.log(value)
}
// 3
// 2
// 1
// 0
31
function createCountdown (start) {
let nextVal = start
return {
[Symbol.iterator]: () => ({
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
})
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function createCountdown (start) {
}
1
let nextVal = start
2
return {
3
[Symbol.iterator]: () => ({
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
})
14
}
15
16
let nextVal = start
function createCountdown (start) {
1
2
return {
3
[Symbol.iterator]: () => ({
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
})
14
}
15
}
16
return {
}
function createCountdown (start) {
1
let nextVal = start
2
3
[Symbol.iterator]: () => ({
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
})
14
15
}
16
[Symbol.iterator]: () => ({
})
function createCountdown (start) {
1
let nextVal = start
2
return {
3
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
14
}
15
}
16
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
function createCountdown (start) {
1
let nextVal = start
2
return {
3
[Symbol.iterator]: () => ({
4
5
6
7
8
9
10
11
12
13
})
14
}
15
}
16
@loige
Countdown iterable
const countdown = createCountdown(3)
for (const value of countdown) {
console.log(value)
}
// 3
// 2
// 1
// 0
31
function createCountdown (start) {
let nextVal = start
return {
[Symbol.iterator]: () => ({
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
})
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function createCountdown (start) {
}
1
let nextVal = start
2
return {
3
[Symbol.iterator]: () => ({
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
})
14
}
15
16
let nextVal = start
function createCountdown (start) {
1
2
return {
3
[Symbol.iterator]: () => ({
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
})
14
}
15
}
16
return {
}
function createCountdown (start) {
1
let nextVal = start
2
3
[Symbol.iterator]: () => ({
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
})
14
15
}
16
[Symbol.iterator]: () => ({
})
function createCountdown (start) {
1
let nextVal = start
2
return {
3
4
next () {
5
if (nextVal < 0) {
6
return { done: true }
7
}
8
return {
9
done: false,
10
value: nextVal--
11
}
12
}
13
14
}
15
}
16
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
function createCountdown (start) {
1
let nextVal = start
2
return {
3
[Symbol.iterator]: () => ({
4
5
6
7
8
9
10
11
12
13
})
14
}
15
}
16
function createCountdown (start) {
let nextVal = start
return {
[Symbol.iterator]: () => ({
next () {
if (nextVal < 0) {
return { done: true }
}
return {
done: false,
value: nextVal--
}
}
})
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@loige
Countdown iterable
const countdown = createCountdown(3)
for (const value of countdown) {
console.log(value)
}
// 3
// 2
// 1
// 0
31
Can an object be both an
iterator and an iterable?! 🤨
@loige
32
const iterableIterator = {
next() {
return { done: false, value: "hello" }
},
[Symbol.iterator]() {
return this
}
}
1
2
3
4
5
6
7
8
@loige
Iterator + Iterable
33
const iterableIterator = {
next() {
return { done: false, value: "hello" }
},
[Symbol.iterator]() {
return this
}
}
1
2
3
4
5
6
7
8
const iterableIterator = {
}
1
next() {
2
return { done: false, value: "hello" }
3
},
4
[Symbol.iterator]() {
5
return this
6
}
7
8
@loige
Iterator + Iterable
iterableIterator.next()
// { done: false, value: "hello" }
for (const value of iterableIterator) {
console.log(value)
}
// hello
// hello
// hello
// ...
33
const iterableIterator = {
next() {
return { done: false, value: "hello" }
},
[Symbol.iterator]() {
return this
}
}
1
2
3
4
5
6
7
8
const iterableIterator = {
}
1
next() {
2
return { done: false, value: "hello" }
3
},
4
[Symbol.iterator]() {
5
return this
6
}
7
8
next() {
return { done: false, value: "hello" }
},
const iterableIterator = {
1
2
3
4
[Symbol.iterator]() {
5
return this
6
}
7
}
8
@loige
Iterator + Iterable
iterableIterator.next()
// { done: false, value: "hello" }
for (const value of iterableIterator) {
console.log(value)
}
// hello
// hello
// hello
// ...
33
const iterableIterator = {
next() {
return { done: false, value: "hello" }
},
[Symbol.iterator]() {
return this
}
}
1
2
3
4
5
6
7
8
const iterableIterator = {
}
1
next() {
2
return { done: false, value: "hello" }
3
},
4
[Symbol.iterator]() {
5
return this
6
}
7
8
next() {
return { done: false, value: "hello" }
},
const iterableIterator = {
1
2
3
4
[Symbol.iterator]() {
5
return this
6
}
7
}
8
[Symbol.iterator]() {
return this
}
const iterableIterator = {
1
next() {
2
return { done: false, value: "hello" }
3
},
4
5
6
7
}
8
@loige
Iterator + Iterable
iterableIterator.next()
// { done: false, value: "hello" }
for (const value of iterableIterator) {
console.log(value)
}
// hello
// hello
// hello
// ...
33
const iterableIterator = {
next() {
return { done: false, value: "hello" }
},
[Symbol.iterator]() {
return this
}
}
1
2
3
4
5
6
7
8
const iterableIterator = {
}
1
next() {
2
return { done: false, value: "hello" }
3
},
4
[Symbol.iterator]() {
5
return this
6
}
7
8
next() {
return { done: false, value: "hello" }
},
const iterableIterator = {
1
2
3
4
[Symbol.iterator]() {
5
return this
6
}
7
}
8
[Symbol.iterator]() {
return this
}
const iterableIterator = {
1
next() {
2
return { done: false, value: "hello" }
3
},
4
5
6
7
}
8
const iterableIterator = {
next() {
return { done: false, value: "hello" }
},
[Symbol.iterator]() {
return this
}
}
1
2
3
4
5
6
7
8
@loige
Iterator + Iterable
iterableIterator.next()
// { done: false, value: "hello" }
for (const value of iterableIterator) {
console.log(value)
}
// hello
// hello
// hello
// ...
33
Generators
A generator function "produces" an
object that is both an iterator and an
iterable! 🤯
@loige
34
function * createCountdown (start) {
for (let i = start; i >= 0; i--) {
yield i
}
}
1
2
3
4
5
@loige
35
function * createCountdown (start) {
for (let i = start; i >= 0; i--) {
yield i
}
}
1
2
3
4
5
function * createCountdown (start) {
}
1
for (let i = start; i >= 0; i--) {
2
yield i
3
}
4
5
@loige
// As iterator
const countdown = createCountdown(3)
console.log(countdown.next()) // { done: false, value: 3 }
console.log(countdown.next()) // { done: false, value: 2 }
console.log(countdown.next()) // { done: false, value: 1 }
console.log(countdown.next()) // { done: false, value: 0 }
console.log(countdown.next()) // { done: true }
35
function * createCountdown (start) {
for (let i = start; i >= 0; i--) {
yield i
}
}
1
2
3
4
5
function * createCountdown (start) {
}
1
for (let i = start; i >= 0; i--) {
2
yield i
3
}
4
5
for (let i = start; i >= 0; i--) {
}
function * createCountdown (start) {
1
2
yield i
3
4
}
5
@loige
// As iterable
const countdown = createCountdown(3)
for (const value of countdown) {
console.log(value)
}
// 3
// 2
// 1
// 0
// As iterator
const countdown = createCountdown(3)
console.log(countdown.next()) // { done: false, value: 3 }
console.log(countdown.next()) // { done: false, value: 2 }
console.log(countdown.next()) // { done: false, value: 1 }
console.log(countdown.next()) // { done: false, value: 0 }
console.log(countdown.next()) // { done: true }
35
function * createCountdown (start) {
for (let i = start; i >= 0; i--) {
yield i
}
}
1
2
3
4
5
function * createCountdown (start) {
}
1
for (let i = start; i >= 0; i--) {
2
yield i
3
}
4
5
for (let i = start; i >= 0; i--) {
}
function * createCountdown (start) {
1
2
yield i
3
4
}
5
yield i
function * createCountdown (start) {
1
for (let i = start; i >= 0; i--) {
2
3
}
4
}
5
@loige
// As iterable
const countdown = createCountdown(3)
for (const value of countdown) {
console.log(value)
}
// 3
// 2
// 1
// 0
// As iterator
const countdown = createCountdown(3)
console.log(countdown.next()) // { done: false, value: 3 }
console.log(countdown.next()) // { done: false, value: 2 }
console.log(countdown.next()) // { done: false, value: 1 }
console.log(countdown.next()) // { done: false, value: 0 }
console.log(countdown.next()) // { done: true }
35
function * createCountdown (start) {
for (let i = start; i >= 0; i--) {
yield i
}
}
1
2
3
4
5
function * createCountdown (start) {
}
1
for (let i = start; i >= 0; i--) {
2
yield i
3
}
4
5
for (let i = start; i >= 0; i--) {
}
function * createCountdown (start) {
1
2
yield i
3
4
}
5
yield i
function * createCountdown (start) {
1
for (let i = start; i >= 0; i--) {
2
3
}
4
}
5
function * createCountdown (start) {
for (let i = start; i >= 0; i--) {
yield i
}
}
1
2
3
4
5
@loige
// As iterable
const countdown = createCountdown(3)
for (const value of countdown) {
console.log(value)
}
// 3
// 2
// 1
// 0
// As iterator
const countdown = createCountdown(3)
console.log(countdown.next()) // { done: false, value: 3 }
console.log(countdown.next()) // { done: false, value: 2 }
console.log(countdown.next()) // { done: false, value: 1 }
console.log(countdown.next()) // { done: false, value: 0 }
console.log(countdown.next()) // { done: true }
35
Well, what about async
iteration?
@loige
36
Async Iterator protocol
An object is an async iterator if it has a next() method. Every
time you call it, it returns a promise that resolves to an
object with the keys done (boolean) and value.
@loige
37
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@loige
38
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
@loige
38
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
function createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
14
@loige
const countdown = createAsyncCountdown(3)
console.log(await countdown.next()) // { done: false, value: 3 }
console.log(await countdown.next()) // { done: false, value: 2 }
console.log(await countdown.next()) // { done: false, value: 1 }
console.log(await countdown.next()) // { done: false, value: 0 }
console.log(await countdown.next()) // { done: true }
38
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
function createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
14
let nextVal = start
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
@loige
const countdown = createAsyncCountdown(3)
console.log(await countdown.next()) // { done: false, value: 3 }
console.log(await countdown.next()) // { done: false, value: 2 }
console.log(await countdown.next()) // { done: false, value: 1 }
console.log(await countdown.next()) // { done: false, value: 0 }
console.log(await countdown.next()) // { done: true }
38
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
function createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
14
let nextVal = start
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
return {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
13
}
14
@loige
const countdown = createAsyncCountdown(3)
console.log(await countdown.next()) // { done: false, value: 3 }
console.log(await countdown.next()) // { done: false, value: 2 }
console.log(await countdown.next()) // { done: false, value: 1 }
console.log(await countdown.next()) // { done: false, value: 0 }
console.log(await countdown.next()) // { done: true }
38
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
function createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
14
let nextVal = start
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
return {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
13
}
14
async next () {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
12
}
13
}
14
@loige
const countdown = createAsyncCountdown(3)
console.log(await countdown.next()) // { done: false, value: 3 }
console.log(await countdown.next()) // { done: false, value: 2 }
console.log(await countdown.next()) // { done: false, value: 1 }
console.log(await countdown.next()) // { done: false, value: 0 }
console.log(await countdown.next()) // { done: true }
38
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
function createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
14
let nextVal = start
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
return {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
13
}
14
async next () {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
12
}
13
}
14
await setTimeout(delay)
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
async next () {
6
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
@loige
const countdown = createAsyncCountdown(3)
console.log(await countdown.next()) // { done: false, value: 3 }
console.log(await countdown.next()) // { done: false, value: 2 }
console.log(await countdown.next()) // { done: false, value: 1 }
console.log(await countdown.next()) // { done: false, value: 0 }
console.log(await countdown.next()) // { done: true }
38
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
function createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
14
let nextVal = start
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
return {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
13
}
14
async next () {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
12
}
13
}
14
await setTimeout(delay)
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
async next () {
6
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
8
9
10
11
}
12
}
13
}
14
@loige
const countdown = createAsyncCountdown(3)
console.log(await countdown.next()) // { done: false, value: 3 }
console.log(await countdown.next()) // { done: false, value: 2 }
console.log(await countdown.next()) // { done: false, value: 1 }
console.log(await countdown.next()) // { done: false, value: 0 }
console.log(await countdown.next()) // { done: true }
38
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
function createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
14
let nextVal = start
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
4
return {
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
return {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
5
async next () {
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
13
}
14
async next () {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
6
await setTimeout(delay)
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
12
}
13
}
14
await setTimeout(delay)
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
async next () {
6
7
if (nextVal < 0) {
8
return { done: true }
9
}
10
return { done: false, value: nextVal-- }
11
}
12
}
13
}
14
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
let nextVal = start
4
return {
5
async next () {
6
await setTimeout(delay)
7
8
9
10
11
}
12
}
13
}
14
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@loige
const countdown = createAsyncCountdown(3)
console.log(await countdown.next()) // { done: false, value: 3 }
console.log(await countdown.next()) // { done: false, value: 2 }
console.log(await countdown.next()) // { done: false, value: 1 }
console.log(await countdown.next()) // { done: false, value: 0 }
console.log(await countdown.next()) // { done: true }
38
@loige
39
Async Iterable protocol
An object is an async iterable if it implements the
@@asyncIterator* method, a zero-argument function that
returns an async iterator.
 
* Symbol.asyncIterator
@loige
40
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
return {
[Symbol.asyncIterator]: function () {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@loige
41
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
return {
[Symbol.asyncIterator]: function () {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
17
}
18
@loige
41
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
return {
[Symbol.asyncIterator]: function () {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
17
}
18
return {
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
}
17
}
18
@loige
const countdown = createAsyncCountdown(3)
for await (const value of countdown) {
console.log(value) // 3 ... 2 ... 1 ... 0
}
41
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
return {
[Symbol.asyncIterator]: function () {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
17
}
18
return {
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
}
17
}
18
[Symbol.asyncIterator]: function () {
return { done: false, value: nextVal-- }
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
13
}
14
}
15
}
16
}
17
}
18
@loige
const countdown = createAsyncCountdown(3)
for await (const value of countdown) {
console.log(value) // 3 ... 2 ... 1 ... 0
}
41
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
return {
[Symbol.asyncIterator]: function () {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
17
}
18
return {
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
}
17
}
18
[Symbol.asyncIterator]: function () {
return { done: false, value: nextVal-- }
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
13
}
14
}
15
}
16
}
17
}
18
let nextVal = start
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
[Symbol.asyncIterator]: function () {
5
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
}
17
}
18
@loige
const countdown = createAsyncCountdown(3)
for await (const value of countdown) {
console.log(value) // 3 ... 2 ... 1 ... 0
}
41
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
return {
[Symbol.asyncIterator]: function () {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
17
}
18
return {
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
}
17
}
18
[Symbol.asyncIterator]: function () {
return { done: false, value: nextVal-- }
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
13
}
14
}
15
}
16
}
17
}
18
let nextVal = start
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
[Symbol.asyncIterator]: function () {
5
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
}
17
}
18
return {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
15
}
16
}
17
}
18
@loige
const countdown = createAsyncCountdown(3)
for await (const value of countdown) {
console.log(value) // 3 ... 2 ... 1 ... 0
}
41
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
return {
[Symbol.asyncIterator]: function () {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
17
}
18
return {
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
}
17
}
18
[Symbol.asyncIterator]: function () {
return { done: false, value: nextVal-- }
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
13
}
14
}
15
}
16
}
17
}
18
let nextVal = start
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
[Symbol.asyncIterator]: function () {
5
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
}
17
}
18
return {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
15
}
16
}
17
}
18
async next () {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
14
}
15
}
16
}
17
}
18
@loige
const countdown = createAsyncCountdown(3)
for await (const value of countdown) {
console.log(value) // 3 ... 2 ... 1 ... 0
}
41
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
return {
[Symbol.asyncIterator]: function () {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
17
}
18
return {
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
}
17
}
18
[Symbol.asyncIterator]: function () {
return { done: false, value: nextVal-- }
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
13
}
14
}
15
}
16
}
17
}
18
let nextVal = start
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
[Symbol.asyncIterator]: function () {
5
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
}
17
}
18
return {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
15
}
16
}
17
}
18
async next () {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
14
}
15
}
16
}
17
}
18
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
9
10
11
12
13
}
14
}
15
}
16
}
17
}
18
@loige
const countdown = createAsyncCountdown(3)
for await (const value of countdown) {
console.log(value) // 3 ... 2 ... 1 ... 0
}
41
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
return {
[Symbol.asyncIterator]: function () {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
17
}
18
return {
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
}
17
}
18
[Symbol.asyncIterator]: function () {
return { done: false, value: nextVal-- }
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
5
let nextVal = start
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
13
}
14
}
15
}
16
}
17
}
18
let nextVal = start
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
[Symbol.asyncIterator]: function () {
5
6
return {
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
}
15
}
16
}
17
}
18
return {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
7
async next () {
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
}
14
15
}
16
}
17
}
18
async next () {
}
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
8
await setTimeout(delay)
9
if (nextVal < 0) {
10
return { done: true }
11
}
12
return { done: false, value: nextVal-- }
13
14
}
15
}
16
}
17
}
18
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
import { setTimeout } from 'timers/promises'
1
2
function createAsyncCountdown (start, delay = 1000) {
3
return {
4
[Symbol.asyncIterator]: function () {
5
let nextVal = start
6
return {
7
async next () {
8
9
10
11
12
13
}
14
}
15
}
16
}
17
}
18
import { setTimeout } from 'timers/promises'
function createAsyncCountdown (start, delay = 1000) {
return {
[Symbol.asyncIterator]: function () {
let nextVal = start
return {
async next () {
await setTimeout(delay)
if (nextVal < 0) {
return { done: true }
}
return { done: false, value: nextVal-- }
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@loige
const countdown = createAsyncCountdown(3)
for await (const value of countdown) {
console.log(value) // 3 ... 2 ... 1 ... 0
}
41
import { setTimeout } from 'timers/promises'
async function * createAsyncCountdown (start, delay = 1000) {
for (let i = start; i >= 0; i--) {
await setTimeout(delay)
yield i
}
}
1
2
3
4
5
6
7
8
@loige
42
import { setTimeout } from 'timers/promises'
async function * createAsyncCountdown (start, delay = 1000) {
for (let i = start; i >= 0; i--) {
await setTimeout(delay)
yield i
}
}
1
2
3
4
5
6
7
8
async function * createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
for (let i = start; i >= 0; i--) {
4
await setTimeout(delay)
5
yield i
6
}
7
8
@loige
const countdown = createAsyncCountdown(3)
for await (const value of countdown) {
console.log(value) // 3 ... 2 ... 1 ... 0
}
42
import { setTimeout } from 'timers/promises'
async function * createAsyncCountdown (start, delay = 1000) {
for (let i = start; i >= 0; i--) {
await setTimeout(delay)
yield i
}
}
1
2
3
4
5
6
7
8
async function * createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
for (let i = start; i >= 0; i--) {
4
await setTimeout(delay)
5
yield i
6
}
7
8
await setTimeout(delay)
yield i
import { setTimeout } from 'timers/promises'
1
2
async function * createAsyncCountdown (start, delay = 1000) {
3
for (let i = start; i >= 0; i--) {
4
5
6
}
7
}
8
@loige
const countdown = createAsyncCountdown(3)
for await (const value of countdown) {
console.log(value) // 3 ... 2 ... 1 ... 0
}
42
import { setTimeout } from 'timers/promises'
async function * createAsyncCountdown (start, delay = 1000) {
for (let i = start; i >= 0; i--) {
await setTimeout(delay)
yield i
}
}
1
2
3
4
5
6
7
8
async function * createAsyncCountdown (start, delay = 1000) {
}
import { setTimeout } from 'timers/promises'
1
2
3
for (let i = start; i >= 0; i--) {
4
await setTimeout(delay)
5
yield i
6
}
7
8
await setTimeout(delay)
yield i
import { setTimeout } from 'timers/promises'
1
2
async function * createAsyncCountdown (start, delay = 1000) {
3
for (let i = start; i >= 0; i--) {
4
5
6
}
7
}
8
import { setTimeout } from 'timers/promises'
async function * createAsyncCountdown (start, delay = 1000) {
for (let i = start; i >= 0; i--) {
await setTimeout(delay)
yield i
}
}
1
2
3
4
5
6
7
8
@loige
const countdown = createAsyncCountdown(3)
for await (const value of countdown) {
console.log(value) // 3 ... 2 ... 1 ... 0
}
42
@loige
43
When to use async iterators
@loige
Sequential iteration pattern
Data arriving in order over time
You need to complete processing the current “chunk”
before you can request the next one
Examples
paginated iteration
consuming tasks from a remote queue
44
Tips & pitfalls ☠
@loige
45
import { createReadStream } from 'fs'
const sourceStream = createReadStream('bigdata.csv')
let bytes = 0
for await (const chunk of sourceStream) {
bytes += chunk.length
}
console.log(`bigdata.csv: ${bytes} bytes`)
1
2
3
4
5
6
7
8
9
10
@loige
Node.js readable streams are async iterators
46
import { createReadStream } from 'fs'
const sourceStream = createReadStream('bigdata.csv')
let bytes = 0
for await (const chunk of sourceStream) {
bytes += chunk.length
}
console.log(`bigdata.csv: ${bytes} bytes`)
1
2
3
4
5
6
7
8
9
10
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
@loige
Node.js readable streams are async iterators
46
import { createReadStream } from 'fs'
const sourceStream = createReadStream('bigdata.csv')
let bytes = 0
for await (const chunk of sourceStream) {
bytes += chunk.length
}
console.log(`bigdata.csv: ${bytes} bytes`)
1
2
3
4
5
6
7
8
9
10
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
const sourceStream = createReadStream('bigdata.csv')
import { createReadStream } from 'fs'
1
2
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
@loige
Node.js readable streams are async iterators
46
import { createReadStream } from 'fs'
const sourceStream = createReadStream('bigdata.csv')
let bytes = 0
for await (const chunk of sourceStream) {
bytes += chunk.length
}
console.log(`bigdata.csv: ${bytes} bytes`)
1
2
3
4
5
6
7
8
9
10
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
const sourceStream = createReadStream('bigdata.csv')
import { createReadStream } from 'fs'
1
2
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
let bytes = 0
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
@loige
Node.js readable streams are async iterators
46
import { createReadStream } from 'fs'
const sourceStream = createReadStream('bigdata.csv')
let bytes = 0
for await (const chunk of sourceStream) {
bytes += chunk.length
}
console.log(`bigdata.csv: ${bytes} bytes`)
1
2
3
4
5
6
7
8
9
10
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
const sourceStream = createReadStream('bigdata.csv')
import { createReadStream } from 'fs'
1
2
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
let bytes = 0
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
for await (const chunk of sourceStream) {
}
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
6
bytes += chunk.length
7
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
@loige
Node.js readable streams are async iterators
46
import { createReadStream } from 'fs'
const sourceStream = createReadStream('bigdata.csv')
let bytes = 0
for await (const chunk of sourceStream) {
bytes += chunk.length
}
console.log(`bigdata.csv: ${bytes} bytes`)
1
2
3
4
5
6
7
8
9
10
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
const sourceStream = createReadStream('bigdata.csv')
import { createReadStream } from 'fs'
1
2
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
let bytes = 0
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
for await (const chunk of sourceStream) {
}
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
6
bytes += chunk.length
7
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
bytes += chunk.length
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
@loige
Node.js readable streams are async iterators
46
import { createReadStream } from 'fs'
const sourceStream = createReadStream('bigdata.csv')
let bytes = 0
for await (const chunk of sourceStream) {
bytes += chunk.length
}
console.log(`bigdata.csv: ${bytes} bytes`)
1
2
3
4
5
6
7
8
9
10
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
const sourceStream = createReadStream('bigdata.csv')
import { createReadStream } from 'fs'
1
2
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
let bytes = 0
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
for await (const chunk of sourceStream) {
}
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
6
bytes += chunk.length
7
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
bytes += chunk.length
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10 console.log(`bigdata.csv: ${bytes} bytes`)
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
10
@loige
Node.js readable streams are async iterators
46
import { createReadStream } from 'fs'
const sourceStream = createReadStream('bigdata.csv')
let bytes = 0
for await (const chunk of sourceStream) {
bytes += chunk.length
}
console.log(`bigdata.csv: ${bytes} bytes`)
1
2
3
4
5
6
7
8
9
10
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
const sourceStream = createReadStream('bigdata.csv')
import { createReadStream } from 'fs'
1
2
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
let bytes = 0
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
for await (const chunk of sourceStream) {
}
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
6
bytes += chunk.length
7
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10
bytes += chunk.length
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
7
}
8
9
console.log(`bigdata.csv: ${bytes} bytes`)
10 console.log(`bigdata.csv: ${bytes} bytes`)
import { createReadStream } from 'fs'
1
2
const sourceStream = createReadStream('bigdata.csv')
3
4
let bytes = 0
5
for await (const chunk of sourceStream) {
6
bytes += chunk.length
7
}
8
9
10
import { createReadStream } from 'fs'
const sourceStream = createReadStream('bigdata.csv')
let bytes = 0
for await (const chunk of sourceStream) {
bytes += chunk.length
}
console.log(`bigdata.csv: ${bytes} bytes`)
1
2
3
4
5
6
7
8
9
10
@loige
Node.js readable streams are async iterators
46
What about
backpressure? 😩
@loige
47
import { createReadStream } from 'fs'
import { once } from 'events'
const sourceStream = createReadStream('bigdata.csv')
const destStream = new SlowTransform()
for await (const chunk of sourceStream) {
const canContinue = destStream.write(chunk)
if (!canContinue) {
// backpressure, now we stop and we need to wait for drain
await once(destStream, 'drain')
// ok now it's safe to resume writing
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@loige
48
import { createReadStream } from 'fs'
import { once } from 'events'
const sourceStream = createReadStream('bigdata.csv')
const destStream = new SlowTransform()
for await (const chunk of sourceStream) {
const canContinue = destStream.write(chunk)
if (!canContinue) {
// backpressure, now we stop and we need to wait for drain
await once(destStream, 'drain')
// ok now it's safe to resume writing
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { createReadStream } from 'fs'
import { once } from 'events'
1
2
3
const sourceStream = createReadStream('bigdata.csv')
4
const destStream = new SlowTransform()
5
6
for await (const chunk of sourceStream) {
7
const canContinue = destStream.write(chunk)
8
if (!canContinue) {
9
// backpressure, now we stop and we need to wait for drain
10
await once(destStream, 'drain')
11
// ok now it's safe to resume writing
12
}
13
}
14
@loige
48
import { createReadStream } from 'fs'
import { once } from 'events'
const sourceStream = createReadStream('bigdata.csv')
const destStream = new SlowTransform()
for await (const chunk of sourceStream) {
const canContinue = destStream.write(chunk)
if (!canContinue) {
// backpressure, now we stop and we need to wait for drain
await once(destStream, 'drain')
// ok now it's safe to resume writing
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { createReadStream } from 'fs'
import { once } from 'events'
1
2
3
const sourceStream = createReadStream('bigdata.csv')
4
const destStream = new SlowTransform()
5
6
for await (const chunk of sourceStream) {
7
const canContinue = destStream.write(chunk)
8
if (!canContinue) {
9
// backpressure, now we stop and we need to wait for drain
10
await once(destStream, 'drain')
11
// ok now it's safe to resume writing
12
}
13
}
14
const sourceStream = createReadStream('bigdata.csv')
import { createReadStream } from 'fs'
1
import { once } from 'events'
2
3
4
const destStream = new SlowTransform()
5
6
for await (const chunk of sourceStream) {
7
const canContinue = destStream.write(chunk)
8
if (!canContinue) {
9
// backpressure, now we stop and we need to wait for drain
10
await once(destStream, 'drain')
11
// ok now it's safe to resume writing
12
}
13
}
14
@loige
48
import { createReadStream } from 'fs'
import { once } from 'events'
const sourceStream = createReadStream('bigdata.csv')
const destStream = new SlowTransform()
for await (const chunk of sourceStream) {
const canContinue = destStream.write(chunk)
if (!canContinue) {
// backpressure, now we stop and we need to wait for drain
await once(destStream, 'drain')
// ok now it's safe to resume writing
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { createReadStream } from 'fs'
import { once } from 'events'
1
2
3
const sourceStream = createReadStream('bigdata.csv')
4
const destStream = new SlowTransform()
5
6
for await (const chunk of sourceStream) {
7
const canContinue = destStream.write(chunk)
8
if (!canContinue) {
9
// backpressure, now we stop and we need to wait for drain
10
await once(destStream, 'drain')
11
// ok now it's safe to resume writing
12
}
13
}
14
const sourceStream = createReadStream('bigdata.csv')
import { createReadStream } from 'fs'
1
import { once } from 'events'
2
3
4
const destStream = new SlowTransform()
5
6
for await (const chunk of sourceStream) {
7
const canContinue = destStream.write(chunk)
8
if (!canContinue) {
9
// backpressure, now we stop and we need to wait for drain
10
await once(destStream, 'drain')
11
// ok now it's safe to resume writing
12
}
13
}
14
const destStream = new SlowTransform()
import { createReadStream } from 'fs'
1
import { once } from 'events'
2
3
const sourceStream = createReadStream('bigdata.csv')
4
5
6
for await (const chunk of sourceStream) {
7
const canContinue = destStream.write(chunk)
8
if (!canContinue) {
9
// backpressure, now we stop and we need to wait for drain
10
await once(destStream, 'drain')
11
// ok now it's safe to resume writing
12
}
13
}
14
@loige
48
import { createReadStream } from 'fs'
import { once } from 'events'
const sourceStream = createReadStream('bigdata.csv')
const destStream = new SlowTransform()
for await (const chunk of sourceStream) {
const canContinue = destStream.write(chunk)
if (!canContinue) {
// backpressure, now we stop and we need to wait for drain
await once(destStream, 'drain')
// ok now it's safe to resume writing
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { createReadStream } from 'fs'
import { once } from 'events'
1
2
3
const sourceStream = createReadStream('bigdata.csv')
4
const destStream = new SlowTransform()
5
6
for await (const chunk of sourceStream) {
7
const canContinue = destStream.write(chunk)
8
if (!canContinue) {
9
// backpressure, now we stop and we need to wait for drain
10
await once(destStream, 'drain')
11
// ok now it's safe to resume writing
12
}
13
}
14
const sourceStream = createReadStream('bigdata.csv')
import { createReadStream } from 'fs'
1
import { once } from 'events'
2
3
4
const destStream = new SlowTransform()
5
6
for await (const chunk of sourceStream) {
7
const canContinue = destStream.write(chunk)
8
if (!canContinue) {
9
// backpressure, now we stop and we need to wait for drain
10
await once(destStream, 'drain')
11
// ok now it's safe to resume writing
12
}
13
}
14
const destStream = new SlowTransform()
import { createReadStream } from 'fs'
1
import { once } from 'events'
2
3
const sourceStream = createReadStream('bigdata.csv')
4
5
6
for await (const chunk of sourceStream) {
7
const canContinue = destStream.write(chunk)
8
if (!canContinue) {
9
// backpressure, now we stop and we need to wait for drain
10
await once(destStream, 'drain')
11
// ok now it's safe to resume writing
12
}
13
}
14
for await (const chunk of sourceStream) {
}
import { createReadStream } from 'fs'
1
import { once } from 'events'
2
3
const sourceStream = createReadStream('bigdata.csv')
4
const destStream = new SlowTransform()
5
6
7
const canContinue = destStream.write(chunk)
8
if (!canContinue) {
9
// backpressure, now we stop and we need to wait for drain
10
await once(destStream, 'drain')
11
// ok now it's safe to resume writing
12
}
13
14
@loige
48
import { createReadStream } from 'fs'
import { once } from 'events'
const sourceStream = createReadStream('bigdata.csv')
const destStream = new SlowTransform()
for await (const chunk of sourceStream) {
const canContinue = destStream.write(chunk)
if (!canContinue) {
// backpressure, now we stop and we need to wait for drain
await once(destStream, 'drain')
// ok now it's safe to resume writing
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { createReadStream } from 'fs'
import { once } from 'events'
1
2
3
const sourceStream = createReadStream('bigdata.csv')
4
const destStream = new SlowTransform()
5
6
for await (const chunk of sourceStream) {
7
const canContinue = destStream.write(chunk)
8
if (!canContinue) {
9
// backpressure, now we stop and we need to wait for drain
10
await once(destStream, 'drain')
11
// ok now it's safe to resume writing
12
}
13
}
14
const sourceStream = createReadStream('bigdata.csv')
import { createReadStream } from 'fs'
1
import { once } from 'events'
2
3
4
const destStream = new SlowTransform()
5
6
for await (const chunk of sourceStream) {
7
const canContinue = destStream.write(chunk)
8
if (!canContinue) {
9
// backpressure, now we stop and we need to wait for drain
10
await once(destStream, 'drain')
11
// ok now it's safe to resume writing
12
}
13
}
14
const destStream = new SlowTransform()
import { createReadStream } from 'fs'
1
import { once } from 'events'
2
3
const sourceStream = createReadStream('bigdata.csv')
4
5
6
for await (const chunk of sourceStream) {
7
const canContinue = destStream.write(chunk)
8
if (!canContinue) {
9
// backpressure, now we stop and we need to wait for drain
10
await once(destStream, 'drain')
11
// ok now it's safe to resume writing
12
}
13
}
14
for await (const chunk of sourceStream) {
}
import { createReadStream } from 'fs'
1
import { once } from 'events'
2
3
const sourceStream = createReadStream('bigdata.csv')
4
const destStream = new SlowTransform()
5
6
7
const canContinue = destStream.write(chunk)
8
if (!canContinue) {
9
// backpressure, now we stop and we need to wait for drain
10
await once(destStream, 'drain')
11
// ok now it's safe to resume writing
12
}
13
14
const canContinue = destStream.write(chunk)
import { createReadStream } from 'fs'
1
import { once } from 'events'
2
3
const sourceStream = createReadStream('bigdata.csv')
4
const destStream = new SlowTransform()
5
6
for await (const chunk of sourceStream) {
7
8
if (!canContinue) {
9
// backpressure, now we stop and we need to wait for drain
10
await once(destStream, 'drain')
11
// ok now it's safe to resume writing
12
}
13
}
14
@loige
48
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained
JavaScript & Node.js Iterators Explained

More Related Content

What's hot

Raspberry Pi à la GroovyFX
Raspberry Pi à la GroovyFXRaspberry Pi à la GroovyFX
Raspberry Pi à la GroovyFXStephen Chin
 
The Ring programming language version 1.2 book - Part 35 of 84
The Ring programming language version 1.2 book - Part 35 of 84The Ring programming language version 1.2 book - Part 35 of 84
The Ring programming language version 1.2 book - Part 35 of 84Mahmoud Samir Fayed
 
The Ring programming language version 1.4.1 book - Part 13 of 31
The Ring programming language version 1.4.1 book - Part 13 of 31The Ring programming language version 1.4.1 book - Part 13 of 31
The Ring programming language version 1.4.1 book - Part 13 of 31Mahmoud Samir Fayed
 
The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189Mahmoud Samir Fayed
 
The Ring programming language version 1.10 book - Part 64 of 212
The Ring programming language version 1.10 book - Part 64 of 212The Ring programming language version 1.10 book - Part 64 of 212
The Ring programming language version 1.10 book - Part 64 of 212Mahmoud Samir Fayed
 
The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.9 book - Part 53 of 210The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.9 book - Part 53 of 210Mahmoud Samir Fayed
 
The Ring programming language version 1.8 book - Part 53 of 202
The Ring programming language version 1.8 book - Part 53 of 202The Ring programming language version 1.8 book - Part 53 of 202
The Ring programming language version 1.8 book - Part 53 of 202Mahmoud Samir Fayed
 
PyCon2009_AI_Alt
PyCon2009_AI_AltPyCon2009_AI_Alt
PyCon2009_AI_AltHiroshi Ono
 
RxJS 5 in Depth
RxJS 5 in DepthRxJS 5 in Depth
RxJS 5 in DepthC4Media
 
java experiments and programs
java experiments and programsjava experiments and programs
java experiments and programsKaruppaiyaa123
 
The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189Mahmoud Samir Fayed
 
Haskellで学ぶ関数型言語
Haskellで学ぶ関数型言語Haskellで学ぶ関数型言語
Haskellで学ぶ関数型言語ikdysfm
 
The Ring programming language version 1.10 book - Part 56 of 212
The Ring programming language version 1.10 book - Part 56 of 212The Ring programming language version 1.10 book - Part 56 of 212
The Ring programming language version 1.10 book - Part 56 of 212Mahmoud Samir Fayed
 
Capability Driven Design - Andrzej Jóźwiak - TomTom Dev Day 2021
Capability Driven Design - Andrzej Jóźwiak  - TomTom Dev Day 2021Capability Driven Design - Andrzej Jóźwiak  - TomTom Dev Day 2021
Capability Driven Design - Andrzej Jóźwiak - TomTom Dev Day 2021Andrzej Jóźwiak
 
Simulator customizing & testing for Xcode 9
Simulator customizing & testing for Xcode 9Simulator customizing & testing for Xcode 9
Simulator customizing & testing for Xcode 9Bongwon Lee
 
The Ring programming language version 1.5.1 book - Part 51 of 180
The Ring programming language version 1.5.1 book - Part 51 of 180The Ring programming language version 1.5.1 book - Part 51 of 180
The Ring programming language version 1.5.1 book - Part 51 of 180Mahmoud Samir Fayed
 
The Ring programming language version 1.8 book - Part 35 of 202
The Ring programming language version 1.8 book - Part 35 of 202The Ring programming language version 1.8 book - Part 35 of 202
The Ring programming language version 1.8 book - Part 35 of 202Mahmoud Samir Fayed
 

What's hot (20)

Raspberry Pi à la GroovyFX
Raspberry Pi à la GroovyFXRaspberry Pi à la GroovyFX
Raspberry Pi à la GroovyFX
 
The Ring programming language version 1.2 book - Part 35 of 84
The Ring programming language version 1.2 book - Part 35 of 84The Ring programming language version 1.2 book - Part 35 of 84
The Ring programming language version 1.2 book - Part 35 of 84
 
The Ring programming language version 1.4.1 book - Part 13 of 31
The Ring programming language version 1.4.1 book - Part 13 of 31The Ring programming language version 1.4.1 book - Part 13 of 31
The Ring programming language version 1.4.1 book - Part 13 of 31
 
The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189
 
The Ring programming language version 1.10 book - Part 64 of 212
The Ring programming language version 1.10 book - Part 64 of 212The Ring programming language version 1.10 book - Part 64 of 212
The Ring programming language version 1.10 book - Part 64 of 212
 
The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.9 book - Part 53 of 210The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.9 book - Part 53 of 210
 
The Ring programming language version 1.8 book - Part 53 of 202
The Ring programming language version 1.8 book - Part 53 of 202The Ring programming language version 1.8 book - Part 53 of 202
The Ring programming language version 1.8 book - Part 53 of 202
 
PyCon2009_AI_Alt
PyCon2009_AI_AltPyCon2009_AI_Alt
PyCon2009_AI_Alt
 
Mini-curso JavaFX Aula2
Mini-curso JavaFX Aula2Mini-curso JavaFX Aula2
Mini-curso JavaFX Aula2
 
RxJS 5 in Depth
RxJS 5 in DepthRxJS 5 in Depth
RxJS 5 in Depth
 
java experiments and programs
java experiments and programsjava experiments and programs
java experiments and programs
 
Connect 4
Connect 4Connect 4
Connect 4
 
Lambda expressions in C++
Lambda expressions in C++Lambda expressions in C++
Lambda expressions in C++
 
The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189
 
Haskellで学ぶ関数型言語
Haskellで学ぶ関数型言語Haskellで学ぶ関数型言語
Haskellで学ぶ関数型言語
 
The Ring programming language version 1.10 book - Part 56 of 212
The Ring programming language version 1.10 book - Part 56 of 212The Ring programming language version 1.10 book - Part 56 of 212
The Ring programming language version 1.10 book - Part 56 of 212
 
Capability Driven Design - Andrzej Jóźwiak - TomTom Dev Day 2021
Capability Driven Design - Andrzej Jóźwiak  - TomTom Dev Day 2021Capability Driven Design - Andrzej Jóźwiak  - TomTom Dev Day 2021
Capability Driven Design - Andrzej Jóźwiak - TomTom Dev Day 2021
 
Simulator customizing & testing for Xcode 9
Simulator customizing & testing for Xcode 9Simulator customizing & testing for Xcode 9
Simulator customizing & testing for Xcode 9
 
The Ring programming language version 1.5.1 book - Part 51 of 180
The Ring programming language version 1.5.1 book - Part 51 of 180The Ring programming language version 1.5.1 book - Part 51 of 180
The Ring programming language version 1.5.1 book - Part 51 of 180
 
The Ring programming language version 1.8 book - Part 35 of 202
The Ring programming language version 1.8 book - Part 35 of 202The Ring programming language version 1.8 book - Part 35 of 202
The Ring programming language version 1.8 book - Part 35 of 202
 

Similar to JavaScript & Node.js Iterators Explained

The Ring programming language version 1.7 book - Part 64 of 196
The Ring programming language version 1.7 book - Part 64 of 196The Ring programming language version 1.7 book - Part 64 of 196
The Ring programming language version 1.7 book - Part 64 of 196Mahmoud Samir Fayed
 
Declare Your Language: Transformation by Strategic Term Rewriting
Declare Your Language: Transformation by Strategic Term RewritingDeclare Your Language: Transformation by Strategic Term Rewriting
Declare Your Language: Transformation by Strategic Term RewritingEelco Visser
 
Please follow the data 1) For Line 23 In the IF - Condition yo.pdf
Please follow the data 1) For Line 23 In the IF - Condition yo.pdfPlease follow the data 1) For Line 23 In the IF - Condition yo.pdf
Please follow the data 1) For Line 23 In the IF - Condition yo.pdfinfo382133
 
Go Says WAT?
Go Says WAT?Go Says WAT?
Go Says WAT?jonbodner
 
ECMAScript2015
ECMAScript2015ECMAScript2015
ECMAScript2015qmmr
 
groovy databases
groovy databasesgroovy databases
groovy databasesPaul King
 
Just in time (series) - KairosDB
Just in time (series) - KairosDBJust in time (series) - KairosDB
Just in time (series) - KairosDBVictor Anjos
 
Slaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubySlaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubyJason Yeo Jie Shun
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019corehard_by
 
Gems of GameplayKit. UA Mobile 2017.
Gems of GameplayKit. UA Mobile 2017.Gems of GameplayKit. UA Mobile 2017.
Gems of GameplayKit. UA Mobile 2017.UA Mobile
 
The Ring programming language version 1.9 book - Part 69 of 210
The Ring programming language version 1.9 book - Part 69 of 210The Ring programming language version 1.9 book - Part 69 of 210
The Ring programming language version 1.9 book - Part 69 of 210Mahmoud Samir Fayed
 
Erlang Introduction Bcberlin3
Erlang Introduction Bcberlin3Erlang Introduction Bcberlin3
Erlang Introduction Bcberlin3guesta3202
 
CS4200 2019 | Lecture 5 | Transformation by Term Rewriting
CS4200 2019 | Lecture 5 | Transformation by Term RewritingCS4200 2019 | Lecture 5 | Transformation by Term Rewriting
CS4200 2019 | Lecture 5 | Transformation by Term RewritingEelco Visser
 
The Ring programming language version 1.5.3 book - Part 69 of 184
The Ring programming language version 1.5.3 book - Part 69 of 184The Ring programming language version 1.5.3 book - Part 69 of 184
The Ring programming language version 1.5.3 book - Part 69 of 184Mahmoud Samir Fayed
 
#include stdafx.h using namespace std; #include stdlib.h.docx
#include stdafx.h using namespace std; #include stdlib.h.docx#include stdafx.h using namespace std; #include stdlib.h.docx
#include stdafx.h using namespace std; #include stdlib.h.docxajoy21
 

Similar to JavaScript & Node.js Iterators Explained (20)

Stop Monkeys Fall
Stop Monkeys FallStop Monkeys Fall
Stop Monkeys Fall
 
The Ring programming language version 1.7 book - Part 64 of 196
The Ring programming language version 1.7 book - Part 64 of 196The Ring programming language version 1.7 book - Part 64 of 196
The Ring programming language version 1.7 book - Part 64 of 196
 
Declare Your Language: Transformation by Strategic Term Rewriting
Declare Your Language: Transformation by Strategic Term RewritingDeclare Your Language: Transformation by Strategic Term Rewriting
Declare Your Language: Transformation by Strategic Term Rewriting
 
Please follow the data 1) For Line 23 In the IF - Condition yo.pdf
Please follow the data 1) For Line 23 In the IF - Condition yo.pdfPlease follow the data 1) For Line 23 In the IF - Condition yo.pdf
Please follow the data 1) For Line 23 In the IF - Condition yo.pdf
 
Go Says WAT?
Go Says WAT?Go Says WAT?
Go Says WAT?
 
ECMAScript2015
ECMAScript2015ECMAScript2015
ECMAScript2015
 
groovy databases
groovy databasesgroovy databases
groovy databases
 
Just in time (series) - KairosDB
Just in time (series) - KairosDBJust in time (series) - KairosDB
Just in time (series) - KairosDB
 
Slaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubySlaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in Ruby
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
 
Gems of GameplayKit. UA Mobile 2017.
Gems of GameplayKit. UA Mobile 2017.Gems of GameplayKit. UA Mobile 2017.
Gems of GameplayKit. UA Mobile 2017.
 
The Magic Of Elixir
The Magic Of ElixirThe Magic Of Elixir
The Magic Of Elixir
 
The Ring programming language version 1.9 book - Part 69 of 210
The Ring programming language version 1.9 book - Part 69 of 210The Ring programming language version 1.9 book - Part 69 of 210
The Ring programming language version 1.9 book - Part 69 of 210
 
Erlang Introduction Bcberlin3
Erlang Introduction Bcberlin3Erlang Introduction Bcberlin3
Erlang Introduction Bcberlin3
 
Programming meeting #8
Programming meeting #8Programming meeting #8
Programming meeting #8
 
CS4200 2019 | Lecture 5 | Transformation by Term Rewriting
CS4200 2019 | Lecture 5 | Transformation by Term RewritingCS4200 2019 | Lecture 5 | Transformation by Term Rewriting
CS4200 2019 | Lecture 5 | Transformation by Term Rewriting
 
The Ring programming language version 1.5.3 book - Part 69 of 184
The Ring programming language version 1.5.3 book - Part 69 of 184The Ring programming language version 1.5.3 book - Part 69 of 184
The Ring programming language version 1.5.3 book - Part 69 of 184
 
C arrays
C arraysC arrays
C arrays
 
Distributed computing with spark
Distributed computing with sparkDistributed computing with spark
Distributed computing with spark
 
#include stdafx.h using namespace std; #include stdlib.h.docx
#include stdafx.h using namespace std; #include stdlib.h.docx#include stdafx.h using namespace std; #include stdlib.h.docx
#include stdafx.h using namespace std; #include stdlib.h.docx
 

More from Luciano Mammino

Did you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJSDid you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJSLuciano Mammino
 
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...Luciano Mammino
 
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS MilanoBuilding an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS MilanoLuciano Mammino
 
From Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperFrom Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperLuciano Mammino
 
Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!Luciano Mammino
 
Everything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLsEverything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLsLuciano Mammino
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance ComputingLuciano Mammino
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance ComputingLuciano Mammino
 
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022Luciano Mammino
 
Building an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & AirtableBuilding an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & AirtableLuciano Mammino
 
Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀Luciano Mammino
 
A look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust DublinA look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust DublinLuciano Mammino
 
Node.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community VijayawadaNode.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community VijayawadaLuciano Mammino
 
A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)Luciano Mammino
 
AWS Observability Made Simple
AWS Observability Made SimpleAWS Observability Made Simple
AWS Observability Made SimpleLuciano Mammino
 
Semplificare l'observability per progetti Serverless
Semplificare l'observability per progetti ServerlessSemplificare l'observability per progetti Serverless
Semplificare l'observability per progetti ServerlessLuciano Mammino
 
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021Luciano Mammino
 
Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021Luciano Mammino
 

More from Luciano Mammino (20)

Did you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJSDid you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJS
 
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
 
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS MilanoBuilding an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
 
From Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperFrom Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiper
 
Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!
 
Everything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLsEverything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLs
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance Computing
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance Computing
 
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
 
Building an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & AirtableBuilding an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & Airtable
 
Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀
 
A look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust DublinA look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust Dublin
 
Monoliths to the cloud!
Monoliths to the cloud!Monoliths to the cloud!
Monoliths to the cloud!
 
The senior dev
The senior devThe senior dev
The senior dev
 
Node.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community VijayawadaNode.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community Vijayawada
 
A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)
 
AWS Observability Made Simple
AWS Observability Made SimpleAWS Observability Made Simple
AWS Observability Made Simple
 
Semplificare l'observability per progetti Serverless
Semplificare l'observability per progetti ServerlessSemplificare l'observability per progetti Serverless
Semplificare l'observability per progetti Serverless
 
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
 
Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021
 

Recently uploaded

08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 

Recently uploaded (20)

08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 

JavaScript & Node.js Iterators Explained

  • 1. Reiterating JavaScript & Node.js iterators Luciano Mammino ( ) @loige loige.link/iter RomaJS - June 16, 2021 1
  • 3. How many ways do you know to "do iteration" in JavaScript & Node.js? 😰 @loige 3
  • 4. for i / for...in / for...of @loige 4
  • 5. while / do while @loige 5
  • 6. Array.forEach / Array.map / Array.flatMap / Array.reduce / Array.reduceRight  / Array.filter / Array.find / Array.findIndex / Array.entries / Array.values / Array.every / Array.some @loige 6
  • 7. Object.keys / Object.values / Object.entries @loige 7
  • 11. Async iterators / Async generators @loige 11
  • 13. That was 28 different concepts! 😳 @loige 13
  • 14. 📝AGENDA Iteration protocols... What? Why? Syntax review Iteration protocols Iterator protocol Iterable protocol Generator functions Async iterator protocol Async iterable protocol Tips & tricks @loige 14
  • 15. Let me introduce myself... @loige 15
  • 16. Let me introduce myself... I'm Luciano ( 🍕🍝) 👋 @loige 15
  • 17. Let me introduce myself... I'm Luciano ( 🍕🍝) 👋  Senior Architect @loige 15
  • 18. Let me introduce myself... I'm Luciano ( 🍕🍝) 👋  Senior Architect nodejsdp.link Co-Author of Node.js Design Patterns  👉 @loige 15
  • 19. Let me introduce myself... I'm Luciano ( 🍕🍝) 👋  Senior Architect nodejsdp.link Co-Author of Node.js Design Patterns  👉 Connect with me:     (blog)   (twitter)   (twitch)   (github) loige.co @loige loige lmammino @loige 15
  • 20. We are business focused technologists that deliver.  |  | Accelerated Serverless AI as a Service Platform Modernisation WE ARE HIRING: Do you want to ? work with us @loige 16
  • 21. Iteration protocols what? why? 🤔 @loige An attempt at standardizing "iteration" behaviors providing a consistent and interoperable API Use for...of, for await...of and spread operator. You can also create lazy iterators You can also deal with async iteration You can create your own custom iterators/iterables 17
  • 23. const judokas = [ 'Driulis Gonzalez Morales', 'Ilias Iliadis', 'Tadahiro Nomura', 'Anton Geesink', 'Teddy Riner', 'Ryoko Tani' ] for (const judoka of judokas) { console.log(judoka) } 1 2 3 4 5 6 7 8 9 10 11 12 @loige for...of 19
  • 24. const judokas = [ 'Driulis Gonzalez Morales', 'Ilias Iliadis', 'Tadahiro Nomura', 'Anton Geesink', 'Teddy Riner', 'Ryoko Tani' ] for (const judoka of judokas) { console.log(judoka) } 1 2 3 4 5 6 7 8 9 10 11 12 const judokas = [ 'Driulis Gonzalez Morales', 'Ilias Iliadis', 'Tadahiro Nomura', 'Anton Geesink', 'Teddy Riner', 'Ryoko Tani' ] 1 2 3 4 5 6 7 8 9 for (const judoka of judokas) { 10 console.log(judoka) 11 } 12 @loige for...of Driulis Gonzalez Morales Ilias Iliadis Tadahiro Nomura Anton Geesink Teddy Riner Ryoko Tani OUTPUT 19
  • 25. const judokas = [ 'Driulis Gonzalez Morales', 'Ilias Iliadis', 'Tadahiro Nomura', 'Anton Geesink', 'Teddy Riner', 'Ryoko Tani' ] for (const judoka of judokas) { console.log(judoka) } 1 2 3 4 5 6 7 8 9 10 11 12 const judokas = [ 'Driulis Gonzalez Morales', 'Ilias Iliadis', 'Tadahiro Nomura', 'Anton Geesink', 'Teddy Riner', 'Ryoko Tani' ] 1 2 3 4 5 6 7 8 9 for (const judoka of judokas) { 10 console.log(judoka) 11 } 12 for (const judoka of judokas) { } const judokas = [ 1 'Driulis Gonzalez Morales', 2 'Ilias Iliadis', 3 'Tadahiro Nomura', 4 'Anton Geesink', 5 'Teddy Riner', 6 'Ryoko Tani' 7 ] 8 9 10 console.log(judoka) 11 12 @loige for...of Driulis Gonzalez Morales Ilias Iliadis Tadahiro Nomura Anton Geesink Teddy Riner Ryoko Tani OUTPUT 19
  • 26. const judokas = [ 'Driulis Gonzalez Morales', 'Ilias Iliadis', 'Tadahiro Nomura', 'Anton Geesink', 'Teddy Riner', 'Ryoko Tani' ] for (const judoka of judokas) { console.log(judoka) } 1 2 3 4 5 6 7 8 9 10 11 12 const judokas = [ 'Driulis Gonzalez Morales', 'Ilias Iliadis', 'Tadahiro Nomura', 'Anton Geesink', 'Teddy Riner', 'Ryoko Tani' ] 1 2 3 4 5 6 7 8 9 for (const judoka of judokas) { 10 console.log(judoka) 11 } 12 for (const judoka of judokas) { } const judokas = [ 1 'Driulis Gonzalez Morales', 2 'Ilias Iliadis', 3 'Tadahiro Nomura', 4 'Anton Geesink', 5 'Teddy Riner', 6 'Ryoko Tani' 7 ] 8 9 10 console.log(judoka) 11 12 console.log(judoka) const judokas = [ 1 'Driulis Gonzalez Morales', 2 'Ilias Iliadis', 3 'Tadahiro Nomura', 4 'Anton Geesink', 5 'Teddy Riner', 6 'Ryoko Tani' 7 ] 8 9 for (const judoka of judokas) { 10 11 } 12 @loige for...of Driulis Gonzalez Morales Ilias Iliadis Tadahiro Nomura Anton Geesink Teddy Riner Ryoko Tani OUTPUT 19
  • 27. const judokas = [ 'Driulis Gonzalez Morales', 'Ilias Iliadis', 'Tadahiro Nomura', 'Anton Geesink', 'Teddy Riner', 'Ryoko Tani' ] for (const judoka of judokas) { console.log(judoka) } 1 2 3 4 5 6 7 8 9 10 11 12 const judokas = [ 'Driulis Gonzalez Morales', 'Ilias Iliadis', 'Tadahiro Nomura', 'Anton Geesink', 'Teddy Riner', 'Ryoko Tani' ] 1 2 3 4 5 6 7 8 9 for (const judoka of judokas) { 10 console.log(judoka) 11 } 12 for (const judoka of judokas) { } const judokas = [ 1 'Driulis Gonzalez Morales', 2 'Ilias Iliadis', 3 'Tadahiro Nomura', 4 'Anton Geesink', 5 'Teddy Riner', 6 'Ryoko Tani' 7 ] 8 9 10 console.log(judoka) 11 12 console.log(judoka) const judokas = [ 1 'Driulis Gonzalez Morales', 2 'Ilias Iliadis', 3 'Tadahiro Nomura', 4 'Anton Geesink', 5 'Teddy Riner', 6 'Ryoko Tani' 7 ] 8 9 for (const judoka of judokas) { 10 11 } 12 const judokas = [ 'Driulis Gonzalez Morales', 'Ilias Iliadis', 'Tadahiro Nomura', 'Anton Geesink', 'Teddy Riner', 'Ryoko Tani' ] for (const judoka of judokas) { console.log(judoka) } 1 2 3 4 5 6 7 8 9 10 11 12 @loige for...of Driulis Gonzalez Morales Ilias Iliadis Tadahiro Nomura Anton Geesink Teddy Riner Ryoko Tani OUTPUT 19
  • 28. const judoka = 'Ryoko Tani' for (const char of judoka) { console.log(char) } 1 2 3 4 5 @loige for...of (with strings) 20
  • 29. const judoka = 'Ryoko Tani' for (const char of judoka) { console.log(char) } 1 2 3 4 5 @loige for...of (with strings) R y o k o T a n i OUTPUT 20
  • 30. const medals = new Set([ 'gold', 'silver', 'bronze' ]) for (const medal of medals) { console.log(medal) } 1 2 3 4 5 6 7 8 9 @loige for...of (with Set) 21
  • 31. const medals = new Set([ 'gold', 'silver', 'bronze' ]) for (const medal of medals) { console.log(medal) } 1 2 3 4 5 6 7 8 9 @loige for...of (with Set)   gold silver bronze OUTPUT 21
  • 32. const medallists = new Map([ ['Teddy Riner', 33], ['Driulis Gonzalez Morales', 16], ['Ryoko Tani', 16], ['Ilias Iliadis', 15] ]) for (const [judoka, medals] of medallists) { console.log(`${judoka} has won ${medals} medals`) } 1 2 3 4 5 6 7 8 9 10 @loige for...of (with Map) 22
  • 33. const medallists = new Map([ ['Teddy Riner', 33], ['Driulis Gonzalez Morales', 16], ['Ryoko Tani', 16], ['Ilias Iliadis', 15] ]) for (const [judoka, medals] of medallists) { console.log(`${judoka} has won ${medals} medals`) } 1 2 3 4 5 6 7 8 9 10 @loige for...of (with Map) Teddy Riner has won 33 medals Driulis Gonzalez Morales has won 16 medals Ryoko Tani has won 16 medals Ilias Iliadis has won 15 medals OUTPUT 22
  • 34. const medallists = { 'Teddy Riner': 33, 'Driulis Gonzalez Morales': 16, 'Ryoko Tani': 16, 'Ilias Iliadis': 15 } for (const [judoka, medals] of Object.entries(medallists)) console.log(`${judoka} has won ${medals} medals`) } 1 2 3 4 5 6 7 8 9 10 @loige for...of (with object & Object.entries) 23
  • 35. const medallists = { 'Teddy Riner': 33, 'Driulis Gonzalez Morales': 16, 'Ryoko Tani': 16, 'Ilias Iliadis': 15 } for (const [judoka, medals] of Object.entries(medallists)) console.log(`${judoka} has won ${medals} medals`) } 1 2 3 4 5 6 7 8 9 10 @loige for...of (with object & Object.entries) Teddy Riner has won 33 medals Driulis Gonzalez Morales has won 16 medals Ryoko Tani has won 16 medals Ilias Iliadis has won 15 medals OUTPUT 23
  • 36. const medallists = { 'Teddy Riner': 33, 'Driulis Gonzalez Morales': 16, 'Ryoko Tani': 16, 'Ilias Iliadis': 15 } for (const [judoka, medals] of medallists) { console.log(`${judoka} has won ${medals} medals`) } 1 2 3 4 5 6 7 8 9 10 @loige for...of (with object literals) 24
  • 37. const medallists = { 'Teddy Riner': 33, 'Driulis Gonzalez Morales': 16, 'Ryoko Tani': 16, 'Ilias Iliadis': 15 } for (const [judoka, medals] of medallists) { console.log(`${judoka} has won ${medals} medals`) } 1 2 3 4 5 6 7 8 9 10 @loige for...of (with object literals) for (const [judoka, medals] of medallists) { ^ TypeError: medallists is not iterable at Object. (.../05-for-of-object.js:8:32) ERROR 24
  • 38. const countdown = [3, 2, 1, 0] // spread into array const from5to0 = [5, 4, ...countdown] console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ] // spread function arguments console.log('countdown data:', ...countdown) // countdown data: 3 2 1 0 1 2 3 4 5 6 7 8 9 @loige Spread operator 25
  • 39. const countdown = [3, 2, 1, 0] // spread into array const from5to0 = [5, 4, ...countdown] console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ] // spread function arguments console.log('countdown data:', ...countdown) // countdown data: 3 2 1 0 1 2 3 4 5 6 7 8 9 const countdown = [3, 2, 1, 0] 1 2 // spread into array 3 const from5to0 = [5, 4, ...countdown] 4 console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ] 5 6 // spread function arguments 7 console.log('countdown data:', ...countdown) 8 // countdown data: 3 2 1 0 9 @loige Spread operator 25
  • 40. const countdown = [3, 2, 1, 0] // spread into array const from5to0 = [5, 4, ...countdown] console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ] // spread function arguments console.log('countdown data:', ...countdown) // countdown data: 3 2 1 0 1 2 3 4 5 6 7 8 9 const countdown = [3, 2, 1, 0] 1 2 // spread into array 3 const from5to0 = [5, 4, ...countdown] 4 console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ] 5 6 // spread function arguments 7 console.log('countdown data:', ...countdown) 8 // countdown data: 3 2 1 0 9 // spread into array const from5to0 = [5, 4, ...countdown] console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ] const countdown = [3, 2, 1, 0] 1 2 3 4 5 6 // spread function arguments 7 console.log('countdown data:', ...countdown) 8 // countdown data: 3 2 1 0 9 @loige Spread operator 25
  • 41. const countdown = [3, 2, 1, 0] // spread into array const from5to0 = [5, 4, ...countdown] console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ] // spread function arguments console.log('countdown data:', ...countdown) // countdown data: 3 2 1 0 1 2 3 4 5 6 7 8 9 const countdown = [3, 2, 1, 0] 1 2 // spread into array 3 const from5to0 = [5, 4, ...countdown] 4 console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ] 5 6 // spread function arguments 7 console.log('countdown data:', ...countdown) 8 // countdown data: 3 2 1 0 9 // spread into array const from5to0 = [5, 4, ...countdown] console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ] const countdown = [3, 2, 1, 0] 1 2 3 4 5 6 // spread function arguments 7 console.log('countdown data:', ...countdown) 8 // countdown data: 3 2 1 0 9 // spread function arguments console.log('countdown data:', ...countdown) // countdown data: 3 2 1 0 const countdown = [3, 2, 1, 0] 1 2 // spread into array 3 const from5to0 = [5, 4, ...countdown] 4 console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ] 5 6 7 8 9 @loige Spread operator 25
  • 42. const countdown = [3, 2, 1, 0] // spread into array const from5to0 = [5, 4, ...countdown] console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ] // spread function arguments console.log('countdown data:', ...countdown) // countdown data: 3 2 1 0 1 2 3 4 5 6 7 8 9 const countdown = [3, 2, 1, 0] 1 2 // spread into array 3 const from5to0 = [5, 4, ...countdown] 4 console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ] 5 6 // spread function arguments 7 console.log('countdown data:', ...countdown) 8 // countdown data: 3 2 1 0 9 // spread into array const from5to0 = [5, 4, ...countdown] console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ] const countdown = [3, 2, 1, 0] 1 2 3 4 5 6 // spread function arguments 7 console.log('countdown data:', ...countdown) 8 // countdown data: 3 2 1 0 9 // spread function arguments console.log('countdown data:', ...countdown) // countdown data: 3 2 1 0 const countdown = [3, 2, 1, 0] 1 2 // spread into array 3 const from5to0 = [5, 4, ...countdown] 4 console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ] 5 6 7 8 9 const countdown = [3, 2, 1, 0] // spread into array const from5to0 = [5, 4, ...countdown] console.log(from5to0) // [ 5, 4, 3, 2, 1, 0 ] // spread function arguments console.log('countdown data:', ...countdown) // countdown data: 3 2 1 0 1 2 3 4 5 6 7 8 9 @loige Spread operator 25
  • 43. import { DynamoDBClient, paginateListTables } from '@aws-sdk/client-dynamodb' const client = new DynamoDBClient({}); for await (const page of paginateListTables({ client }, {})) { // page.TableNames is an array of table names for (const tableName of page.TableNames) { console.log(tableName) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 @loige for await...of (async iterable) 26
  • 44. import { DynamoDBClient, paginateListTables } from '@aws-sdk/client-dynamodb' const client = new DynamoDBClient({}); for await (const page of paginateListTables({ client }, {})) { // page.TableNames is an array of table names for (const tableName of page.TableNames) { console.log(tableName) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 import { DynamoDBClient, paginateListTables } from '@aws-sdk/client-dynamodb' 1 2 3 4 5 const client = new DynamoDBClient({}); 6 7 for await (const page of paginateListTables({ client }, {})) { 8 // page.TableNames is an array of table names 9 for (const tableName of page.TableNames) { 10 console.log(tableName) 11 } 12 } 13 @loige for await...of (async iterable) 26
  • 45. import { DynamoDBClient, paginateListTables } from '@aws-sdk/client-dynamodb' const client = new DynamoDBClient({}); for await (const page of paginateListTables({ client }, {})) { // page.TableNames is an array of table names for (const tableName of page.TableNames) { console.log(tableName) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 import { DynamoDBClient, paginateListTables } from '@aws-sdk/client-dynamodb' 1 2 3 4 5 const client = new DynamoDBClient({}); 6 7 for await (const page of paginateListTables({ client }, {})) { 8 // page.TableNames is an array of table names 9 for (const tableName of page.TableNames) { 10 console.log(tableName) 11 } 12 } 13 const client = new DynamoDBClient({}); import { 1 DynamoDBClient, 2 paginateListTables 3 } from '@aws-sdk/client-dynamodb' 4 5 6 7 for await (const page of paginateListTables({ client }, {})) { 8 // page.TableNames is an array of table names 9 for (const tableName of page.TableNames) { 10 console.log(tableName) 11 } 12 } 13 @loige for await...of (async iterable) 26
  • 46. import { DynamoDBClient, paginateListTables } from '@aws-sdk/client-dynamodb' const client = new DynamoDBClient({}); for await (const page of paginateListTables({ client }, {})) { // page.TableNames is an array of table names for (const tableName of page.TableNames) { console.log(tableName) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 import { DynamoDBClient, paginateListTables } from '@aws-sdk/client-dynamodb' 1 2 3 4 5 const client = new DynamoDBClient({}); 6 7 for await (const page of paginateListTables({ client }, {})) { 8 // page.TableNames is an array of table names 9 for (const tableName of page.TableNames) { 10 console.log(tableName) 11 } 12 } 13 const client = new DynamoDBClient({}); import { 1 DynamoDBClient, 2 paginateListTables 3 } from '@aws-sdk/client-dynamodb' 4 5 6 7 for await (const page of paginateListTables({ client }, {})) { 8 // page.TableNames is an array of table names 9 for (const tableName of page.TableNames) { 10 console.log(tableName) 11 } 12 } 13 for await (const page of paginateListTables({ client }, {})) { } import { 1 DynamoDBClient, 2 paginateListTables 3 } from '@aws-sdk/client-dynamodb' 4 5 const client = new DynamoDBClient({}); 6 7 8 // page.TableNames is an array of table names 9 for (const tableName of page.TableNames) { 10 console.log(tableName) 11 } 12 13 @loige for await...of (async iterable) 26
  • 47. import { DynamoDBClient, paginateListTables } from '@aws-sdk/client-dynamodb' const client = new DynamoDBClient({}); for await (const page of paginateListTables({ client }, {})) { // page.TableNames is an array of table names for (const tableName of page.TableNames) { console.log(tableName) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 import { DynamoDBClient, paginateListTables } from '@aws-sdk/client-dynamodb' 1 2 3 4 5 const client = new DynamoDBClient({}); 6 7 for await (const page of paginateListTables({ client }, {})) { 8 // page.TableNames is an array of table names 9 for (const tableName of page.TableNames) { 10 console.log(tableName) 11 } 12 } 13 const client = new DynamoDBClient({}); import { 1 DynamoDBClient, 2 paginateListTables 3 } from '@aws-sdk/client-dynamodb' 4 5 6 7 for await (const page of paginateListTables({ client }, {})) { 8 // page.TableNames is an array of table names 9 for (const tableName of page.TableNames) { 10 console.log(tableName) 11 } 12 } 13 for await (const page of paginateListTables({ client }, {})) { } import { 1 DynamoDBClient, 2 paginateListTables 3 } from '@aws-sdk/client-dynamodb' 4 5 const client = new DynamoDBClient({}); 6 7 8 // page.TableNames is an array of table names 9 for (const tableName of page.TableNames) { 10 console.log(tableName) 11 } 12 13 // page.TableNames is an array of table names for (const tableName of page.TableNames) { console.log(tableName) } import { 1 DynamoDBClient, 2 paginateListTables 3 } from '@aws-sdk/client-dynamodb' 4 5 const client = new DynamoDBClient({}); 6 7 for await (const page of paginateListTables({ client }, {})) { 8 9 10 11 12 } 13 @loige for await...of (async iterable) 26
  • 48. import { DynamoDBClient, paginateListTables } from '@aws-sdk/client-dynamodb' const client = new DynamoDBClient({}); for await (const page of paginateListTables({ client }, {})) { // page.TableNames is an array of table names for (const tableName of page.TableNames) { console.log(tableName) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 import { DynamoDBClient, paginateListTables } from '@aws-sdk/client-dynamodb' 1 2 3 4 5 const client = new DynamoDBClient({}); 6 7 for await (const page of paginateListTables({ client }, {})) { 8 // page.TableNames is an array of table names 9 for (const tableName of page.TableNames) { 10 console.log(tableName) 11 } 12 } 13 const client = new DynamoDBClient({}); import { 1 DynamoDBClient, 2 paginateListTables 3 } from '@aws-sdk/client-dynamodb' 4 5 6 7 for await (const page of paginateListTables({ client }, {})) { 8 // page.TableNames is an array of table names 9 for (const tableName of page.TableNames) { 10 console.log(tableName) 11 } 12 } 13 for await (const page of paginateListTables({ client }, {})) { } import { 1 DynamoDBClient, 2 paginateListTables 3 } from '@aws-sdk/client-dynamodb' 4 5 const client = new DynamoDBClient({}); 6 7 8 // page.TableNames is an array of table names 9 for (const tableName of page.TableNames) { 10 console.log(tableName) 11 } 12 13 // page.TableNames is an array of table names for (const tableName of page.TableNames) { console.log(tableName) } import { 1 DynamoDBClient, 2 paginateListTables 3 } from '@aws-sdk/client-dynamodb' 4 5 const client = new DynamoDBClient({}); 6 7 for await (const page of paginateListTables({ client }, {})) { 8 9 10 11 12 } 13 import { DynamoDBClient, paginateListTables } from '@aws-sdk/client-dynamodb' const client = new DynamoDBClient({}); for await (const page of paginateListTables({ client }, {})) { // page.TableNames is an array of table names for (const tableName of page.TableNames) { console.log(tableName) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 @loige for await...of (async iterable) 26
  • 50. Iterator protocol In JavaScript, an object is an iterator if it has a next() method. Every time you call it, it returns an object with the keys done (boolean) and value. @loige 28
  • 51. function createCountdown (start) { let nextVal = start return { next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @loige Countdown iterator 29
  • 52. function createCountdown (start) { let nextVal = start return { next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function createCountdown (start) { } 1 let nextVal = start 2 return { 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 14 @loige Countdown iterator const countdown = createCountdown(3) console.log(countdown.next()) // { done: false, value: 3 } console.log(countdown.next()) // { done: false, value: 2 } console.log(countdown.next()) // { done: false, value: 1 } console.log(countdown.next()) // { done: false, value: 0 } console.log(countdown.next()) // { done: true } 29
  • 53. function createCountdown (start) { let nextVal = start return { next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function createCountdown (start) { } 1 let nextVal = start 2 return { 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 14 let nextVal = start function createCountdown (start) { 1 2 return { 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 } 14 @loige Countdown iterator const countdown = createCountdown(3) console.log(countdown.next()) // { done: false, value: 3 } console.log(countdown.next()) // { done: false, value: 2 } console.log(countdown.next()) // { done: false, value: 1 } console.log(countdown.next()) // { done: false, value: 0 } console.log(countdown.next()) // { done: true } 29
  • 54. function createCountdown (start) { let nextVal = start return { next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function createCountdown (start) { } 1 let nextVal = start 2 return { 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 14 let nextVal = start function createCountdown (start) { 1 2 return { 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 } 14 return { } function createCountdown (start) { 1 let nextVal = start 2 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 13 } 14 @loige Countdown iterator const countdown = createCountdown(3) console.log(countdown.next()) // { done: false, value: 3 } console.log(countdown.next()) // { done: false, value: 2 } console.log(countdown.next()) // { done: false, value: 1 } console.log(countdown.next()) // { done: false, value: 0 } console.log(countdown.next()) // { done: true } 29
  • 55. function createCountdown (start) { let nextVal = start return { next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function createCountdown (start) { } 1 let nextVal = start 2 return { 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 14 let nextVal = start function createCountdown (start) { 1 2 return { 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 } 14 return { } function createCountdown (start) { 1 let nextVal = start 2 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 13 } 14 next () { } function createCountdown (start) { 1 let nextVal = start 2 return { 3 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 12 } 13 } 14 @loige Countdown iterator const countdown = createCountdown(3) console.log(countdown.next()) // { done: false, value: 3 } console.log(countdown.next()) // { done: false, value: 2 } console.log(countdown.next()) // { done: false, value: 1 } console.log(countdown.next()) // { done: false, value: 0 } console.log(countdown.next()) // { done: true } 29
  • 56. function createCountdown (start) { let nextVal = start return { next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function createCountdown (start) { } 1 let nextVal = start 2 return { 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 14 let nextVal = start function createCountdown (start) { 1 2 return { 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 } 14 return { } function createCountdown (start) { 1 let nextVal = start 2 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 13 } 14 next () { } function createCountdown (start) { 1 let nextVal = start 2 return { 3 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 12 } 13 } 14 if (nextVal < 0) { return { done: true } } function createCountdown (start) { 1 let nextVal = start 2 return { 3 next () { 4 5 6 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 } 14 @loige Countdown iterator const countdown = createCountdown(3) console.log(countdown.next()) // { done: false, value: 3 } console.log(countdown.next()) // { done: false, value: 2 } console.log(countdown.next()) // { done: false, value: 1 } console.log(countdown.next()) // { done: false, value: 0 } console.log(countdown.next()) // { done: true } 29
  • 57. function createCountdown (start) { let nextVal = start return { next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function createCountdown (start) { } 1 let nextVal = start 2 return { 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 14 let nextVal = start function createCountdown (start) { 1 2 return { 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 } 14 return { } function createCountdown (start) { 1 let nextVal = start 2 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 13 } 14 next () { } function createCountdown (start) { 1 let nextVal = start 2 return { 3 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 12 } 13 } 14 if (nextVal < 0) { return { done: true } } function createCountdown (start) { 1 let nextVal = start 2 return { 3 next () { 4 5 6 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 } 14 return { done: false, value: nextVal-- } function createCountdown (start) { 1 let nextVal = start 2 return { 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 8 9 10 11 } 12 } 13 } 14 @loige Countdown iterator const countdown = createCountdown(3) console.log(countdown.next()) // { done: false, value: 3 } console.log(countdown.next()) // { done: false, value: 2 } console.log(countdown.next()) // { done: false, value: 1 } console.log(countdown.next()) // { done: false, value: 0 } console.log(countdown.next()) // { done: true } 29
  • 58. function createCountdown (start) { let nextVal = start return { next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function createCountdown (start) { } 1 let nextVal = start 2 return { 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 14 let nextVal = start function createCountdown (start) { 1 2 return { 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 } 14 return { } function createCountdown (start) { 1 let nextVal = start 2 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 13 } 14 next () { } function createCountdown (start) { 1 let nextVal = start 2 return { 3 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 12 } 13 } 14 if (nextVal < 0) { return { done: true } } function createCountdown (start) { 1 let nextVal = start 2 return { 3 next () { 4 5 6 7 return { 8 done: false, 9 value: nextVal-- 10 } 11 } 12 } 13 } 14 return { done: false, value: nextVal-- } function createCountdown (start) { 1 let nextVal = start 2 return { 3 next () { 4 if (nextVal < 0) { 5 return { done: true } 6 } 7 8 9 10 11 } 12 } 13 } 14 function createCountdown (start) { let nextVal = start return { next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @loige Countdown iterator const countdown = createCountdown(3) console.log(countdown.next()) // { done: false, value: 3 } console.log(countdown.next()) // { done: false, value: 2 } console.log(countdown.next()) // { done: false, value: 1 } console.log(countdown.next()) // { done: false, value: 0 } console.log(countdown.next()) // { done: true } 29
  • 59. Iterable protocol An object is iterable if it implements the @@iterator* method, a zero-argument function that returns an iterator.   * Symbol.iterator @loige 30
  • 60. function createCountdown (start) { let nextVal = start return { [Symbol.iterator]: () => ({ next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } }) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @loige Countdown iterable 31
  • 61. function createCountdown (start) { let nextVal = start return { [Symbol.iterator]: () => ({ next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } }) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function createCountdown (start) { } 1 let nextVal = start 2 return { 3 [Symbol.iterator]: () => ({ 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 }) 14 } 15 16 @loige Countdown iterable const countdown = createCountdown(3) for (const value of countdown) { console.log(value) } // 3 // 2 // 1 // 0 31
  • 62. function createCountdown (start) { let nextVal = start return { [Symbol.iterator]: () => ({ next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } }) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function createCountdown (start) { } 1 let nextVal = start 2 return { 3 [Symbol.iterator]: () => ({ 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 }) 14 } 15 16 let nextVal = start function createCountdown (start) { 1 2 return { 3 [Symbol.iterator]: () => ({ 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 }) 14 } 15 } 16 @loige Countdown iterable const countdown = createCountdown(3) for (const value of countdown) { console.log(value) } // 3 // 2 // 1 // 0 31
  • 63. function createCountdown (start) { let nextVal = start return { [Symbol.iterator]: () => ({ next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } }) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function createCountdown (start) { } 1 let nextVal = start 2 return { 3 [Symbol.iterator]: () => ({ 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 }) 14 } 15 16 let nextVal = start function createCountdown (start) { 1 2 return { 3 [Symbol.iterator]: () => ({ 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 }) 14 } 15 } 16 return { } function createCountdown (start) { 1 let nextVal = start 2 3 [Symbol.iterator]: () => ({ 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 }) 14 15 } 16 @loige Countdown iterable const countdown = createCountdown(3) for (const value of countdown) { console.log(value) } // 3 // 2 // 1 // 0 31
  • 64. function createCountdown (start) { let nextVal = start return { [Symbol.iterator]: () => ({ next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } }) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function createCountdown (start) { } 1 let nextVal = start 2 return { 3 [Symbol.iterator]: () => ({ 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 }) 14 } 15 16 let nextVal = start function createCountdown (start) { 1 2 return { 3 [Symbol.iterator]: () => ({ 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 }) 14 } 15 } 16 return { } function createCountdown (start) { 1 let nextVal = start 2 3 [Symbol.iterator]: () => ({ 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 }) 14 15 } 16 [Symbol.iterator]: () => ({ }) function createCountdown (start) { 1 let nextVal = start 2 return { 3 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 14 } 15 } 16 @loige Countdown iterable const countdown = createCountdown(3) for (const value of countdown) { console.log(value) } // 3 // 2 // 1 // 0 31
  • 65. function createCountdown (start) { let nextVal = start return { [Symbol.iterator]: () => ({ next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } }) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function createCountdown (start) { } 1 let nextVal = start 2 return { 3 [Symbol.iterator]: () => ({ 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 }) 14 } 15 16 let nextVal = start function createCountdown (start) { 1 2 return { 3 [Symbol.iterator]: () => ({ 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 }) 14 } 15 } 16 return { } function createCountdown (start) { 1 let nextVal = start 2 3 [Symbol.iterator]: () => ({ 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 }) 14 15 } 16 [Symbol.iterator]: () => ({ }) function createCountdown (start) { 1 let nextVal = start 2 return { 3 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 14 } 15 } 16 next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } function createCountdown (start) { 1 let nextVal = start 2 return { 3 [Symbol.iterator]: () => ({ 4 5 6 7 8 9 10 11 12 13 }) 14 } 15 } 16 @loige Countdown iterable const countdown = createCountdown(3) for (const value of countdown) { console.log(value) } // 3 // 2 // 1 // 0 31
  • 66. function createCountdown (start) { let nextVal = start return { [Symbol.iterator]: () => ({ next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } }) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function createCountdown (start) { } 1 let nextVal = start 2 return { 3 [Symbol.iterator]: () => ({ 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 }) 14 } 15 16 let nextVal = start function createCountdown (start) { 1 2 return { 3 [Symbol.iterator]: () => ({ 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 }) 14 } 15 } 16 return { } function createCountdown (start) { 1 let nextVal = start 2 3 [Symbol.iterator]: () => ({ 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 }) 14 15 } 16 [Symbol.iterator]: () => ({ }) function createCountdown (start) { 1 let nextVal = start 2 return { 3 4 next () { 5 if (nextVal < 0) { 6 return { done: true } 7 } 8 return { 9 done: false, 10 value: nextVal-- 11 } 12 } 13 14 } 15 } 16 next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } function createCountdown (start) { 1 let nextVal = start 2 return { 3 [Symbol.iterator]: () => ({ 4 5 6 7 8 9 10 11 12 13 }) 14 } 15 } 16 function createCountdown (start) { let nextVal = start return { [Symbol.iterator]: () => ({ next () { if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } }) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @loige Countdown iterable const countdown = createCountdown(3) for (const value of countdown) { console.log(value) } // 3 // 2 // 1 // 0 31
  • 67. Can an object be both an iterator and an iterable?! 🤨 @loige 32
  • 68. const iterableIterator = { next() { return { done: false, value: "hello" } }, [Symbol.iterator]() { return this } } 1 2 3 4 5 6 7 8 @loige Iterator + Iterable 33
  • 69. const iterableIterator = { next() { return { done: false, value: "hello" } }, [Symbol.iterator]() { return this } } 1 2 3 4 5 6 7 8 const iterableIterator = { } 1 next() { 2 return { done: false, value: "hello" } 3 }, 4 [Symbol.iterator]() { 5 return this 6 } 7 8 @loige Iterator + Iterable iterableIterator.next() // { done: false, value: "hello" } for (const value of iterableIterator) { console.log(value) } // hello // hello // hello // ... 33
  • 70. const iterableIterator = { next() { return { done: false, value: "hello" } }, [Symbol.iterator]() { return this } } 1 2 3 4 5 6 7 8 const iterableIterator = { } 1 next() { 2 return { done: false, value: "hello" } 3 }, 4 [Symbol.iterator]() { 5 return this 6 } 7 8 next() { return { done: false, value: "hello" } }, const iterableIterator = { 1 2 3 4 [Symbol.iterator]() { 5 return this 6 } 7 } 8 @loige Iterator + Iterable iterableIterator.next() // { done: false, value: "hello" } for (const value of iterableIterator) { console.log(value) } // hello // hello // hello // ... 33
  • 71. const iterableIterator = { next() { return { done: false, value: "hello" } }, [Symbol.iterator]() { return this } } 1 2 3 4 5 6 7 8 const iterableIterator = { } 1 next() { 2 return { done: false, value: "hello" } 3 }, 4 [Symbol.iterator]() { 5 return this 6 } 7 8 next() { return { done: false, value: "hello" } }, const iterableIterator = { 1 2 3 4 [Symbol.iterator]() { 5 return this 6 } 7 } 8 [Symbol.iterator]() { return this } const iterableIterator = { 1 next() { 2 return { done: false, value: "hello" } 3 }, 4 5 6 7 } 8 @loige Iterator + Iterable iterableIterator.next() // { done: false, value: "hello" } for (const value of iterableIterator) { console.log(value) } // hello // hello // hello // ... 33
  • 72. const iterableIterator = { next() { return { done: false, value: "hello" } }, [Symbol.iterator]() { return this } } 1 2 3 4 5 6 7 8 const iterableIterator = { } 1 next() { 2 return { done: false, value: "hello" } 3 }, 4 [Symbol.iterator]() { 5 return this 6 } 7 8 next() { return { done: false, value: "hello" } }, const iterableIterator = { 1 2 3 4 [Symbol.iterator]() { 5 return this 6 } 7 } 8 [Symbol.iterator]() { return this } const iterableIterator = { 1 next() { 2 return { done: false, value: "hello" } 3 }, 4 5 6 7 } 8 const iterableIterator = { next() { return { done: false, value: "hello" } }, [Symbol.iterator]() { return this } } 1 2 3 4 5 6 7 8 @loige Iterator + Iterable iterableIterator.next() // { done: false, value: "hello" } for (const value of iterableIterator) { console.log(value) } // hello // hello // hello // ... 33
  • 73. Generators A generator function "produces" an object that is both an iterator and an iterable! 🤯 @loige 34
  • 74. function * createCountdown (start) { for (let i = start; i >= 0; i--) { yield i } } 1 2 3 4 5 @loige 35
  • 75. function * createCountdown (start) { for (let i = start; i >= 0; i--) { yield i } } 1 2 3 4 5 function * createCountdown (start) { } 1 for (let i = start; i >= 0; i--) { 2 yield i 3 } 4 5 @loige // As iterator const countdown = createCountdown(3) console.log(countdown.next()) // { done: false, value: 3 } console.log(countdown.next()) // { done: false, value: 2 } console.log(countdown.next()) // { done: false, value: 1 } console.log(countdown.next()) // { done: false, value: 0 } console.log(countdown.next()) // { done: true } 35
  • 76. function * createCountdown (start) { for (let i = start; i >= 0; i--) { yield i } } 1 2 3 4 5 function * createCountdown (start) { } 1 for (let i = start; i >= 0; i--) { 2 yield i 3 } 4 5 for (let i = start; i >= 0; i--) { } function * createCountdown (start) { 1 2 yield i 3 4 } 5 @loige // As iterable const countdown = createCountdown(3) for (const value of countdown) { console.log(value) } // 3 // 2 // 1 // 0 // As iterator const countdown = createCountdown(3) console.log(countdown.next()) // { done: false, value: 3 } console.log(countdown.next()) // { done: false, value: 2 } console.log(countdown.next()) // { done: false, value: 1 } console.log(countdown.next()) // { done: false, value: 0 } console.log(countdown.next()) // { done: true } 35
  • 77. function * createCountdown (start) { for (let i = start; i >= 0; i--) { yield i } } 1 2 3 4 5 function * createCountdown (start) { } 1 for (let i = start; i >= 0; i--) { 2 yield i 3 } 4 5 for (let i = start; i >= 0; i--) { } function * createCountdown (start) { 1 2 yield i 3 4 } 5 yield i function * createCountdown (start) { 1 for (let i = start; i >= 0; i--) { 2 3 } 4 } 5 @loige // As iterable const countdown = createCountdown(3) for (const value of countdown) { console.log(value) } // 3 // 2 // 1 // 0 // As iterator const countdown = createCountdown(3) console.log(countdown.next()) // { done: false, value: 3 } console.log(countdown.next()) // { done: false, value: 2 } console.log(countdown.next()) // { done: false, value: 1 } console.log(countdown.next()) // { done: false, value: 0 } console.log(countdown.next()) // { done: true } 35
  • 78. function * createCountdown (start) { for (let i = start; i >= 0; i--) { yield i } } 1 2 3 4 5 function * createCountdown (start) { } 1 for (let i = start; i >= 0; i--) { 2 yield i 3 } 4 5 for (let i = start; i >= 0; i--) { } function * createCountdown (start) { 1 2 yield i 3 4 } 5 yield i function * createCountdown (start) { 1 for (let i = start; i >= 0; i--) { 2 3 } 4 } 5 function * createCountdown (start) { for (let i = start; i >= 0; i--) { yield i } } 1 2 3 4 5 @loige // As iterable const countdown = createCountdown(3) for (const value of countdown) { console.log(value) } // 3 // 2 // 1 // 0 // As iterator const countdown = createCountdown(3) console.log(countdown.next()) // { done: false, value: 3 } console.log(countdown.next()) // { done: false, value: 2 } console.log(countdown.next()) // { done: false, value: 1 } console.log(countdown.next()) // { done: false, value: 0 } console.log(countdown.next()) // { done: true } 35
  • 79. Well, what about async iteration? @loige 36
  • 80. Async Iterator protocol An object is an async iterator if it has a next() method. Every time you call it, it returns a promise that resolves to an object with the keys done (boolean) and value. @loige 37
  • 81. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @loige 38
  • 82. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 @loige 38
  • 83. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 function createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 14 @loige const countdown = createAsyncCountdown(3) console.log(await countdown.next()) // { done: false, value: 3 } console.log(await countdown.next()) // { done: false, value: 2 } console.log(await countdown.next()) // { done: false, value: 1 } console.log(await countdown.next()) // { done: false, value: 0 } console.log(await countdown.next()) // { done: true } 38
  • 84. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 function createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 14 let nextVal = start import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 @loige const countdown = createAsyncCountdown(3) console.log(await countdown.next()) // { done: false, value: 3 } console.log(await countdown.next()) // { done: false, value: 2 } console.log(await countdown.next()) // { done: false, value: 1 } console.log(await countdown.next()) // { done: false, value: 0 } console.log(await countdown.next()) // { done: true } 38
  • 85. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 function createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 14 let nextVal = start import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 return { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 13 } 14 @loige const countdown = createAsyncCountdown(3) console.log(await countdown.next()) // { done: false, value: 3 } console.log(await countdown.next()) // { done: false, value: 2 } console.log(await countdown.next()) // { done: false, value: 1 } console.log(await countdown.next()) // { done: false, value: 0 } console.log(await countdown.next()) // { done: true } 38
  • 86. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 function createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 14 let nextVal = start import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 return { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 13 } 14 async next () { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 12 } 13 } 14 @loige const countdown = createAsyncCountdown(3) console.log(await countdown.next()) // { done: false, value: 3 } console.log(await countdown.next()) // { done: false, value: 2 } console.log(await countdown.next()) // { done: false, value: 1 } console.log(await countdown.next()) // { done: false, value: 0 } console.log(await countdown.next()) // { done: true } 38
  • 87. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 function createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 14 let nextVal = start import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 return { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 13 } 14 async next () { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 12 } 13 } 14 await setTimeout(delay) import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 async next () { 6 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 @loige const countdown = createAsyncCountdown(3) console.log(await countdown.next()) // { done: false, value: 3 } console.log(await countdown.next()) // { done: false, value: 2 } console.log(await countdown.next()) // { done: false, value: 1 } console.log(await countdown.next()) // { done: false, value: 0 } console.log(await countdown.next()) // { done: true } 38
  • 88. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 function createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 14 let nextVal = start import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 return { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 13 } 14 async next () { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 12 } 13 } 14 await setTimeout(delay) import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 async next () { 6 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 8 9 10 11 } 12 } 13 } 14 @loige const countdown = createAsyncCountdown(3) console.log(await countdown.next()) // { done: false, value: 3 } console.log(await countdown.next()) // { done: false, value: 2 } console.log(await countdown.next()) // { done: false, value: 1 } console.log(await countdown.next()) // { done: false, value: 0 } console.log(await countdown.next()) // { done: true } 38
  • 89. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 function createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 14 let nextVal = start import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 4 return { 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 return { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 5 async next () { 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 13 } 14 async next () { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 6 await setTimeout(delay) 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 12 } 13 } 14 await setTimeout(delay) import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 async next () { 6 7 if (nextVal < 0) { 8 return { done: true } 9 } 10 return { done: false, value: nextVal-- } 11 } 12 } 13 } 14 if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 let nextVal = start 4 return { 5 async next () { 6 await setTimeout(delay) 7 8 9 10 11 } 12 } 13 } 14 import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @loige const countdown = createAsyncCountdown(3) console.log(await countdown.next()) // { done: false, value: 3 } console.log(await countdown.next()) // { done: false, value: 2 } console.log(await countdown.next()) // { done: false, value: 1 } console.log(await countdown.next()) // { done: false, value: 0 } console.log(await countdown.next()) // { done: true } 38
  • 91. Async Iterable protocol An object is an async iterable if it implements the @@asyncIterator* method, a zero-argument function that returns an async iterator.   * Symbol.asyncIterator @loige 40
  • 92. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { return { [Symbol.asyncIterator]: function () { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @loige 41
  • 93. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { return { [Symbol.asyncIterator]: function () { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 17 } 18 @loige 41
  • 94. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { return { [Symbol.asyncIterator]: function () { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 17 } 18 return { import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 } 17 } 18 @loige const countdown = createAsyncCountdown(3) for await (const value of countdown) { console.log(value) // 3 ... 2 ... 1 ... 0 } 41
  • 95. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { return { [Symbol.asyncIterator]: function () { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 17 } 18 return { import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 } 17 } 18 [Symbol.asyncIterator]: function () { return { done: false, value: nextVal-- } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 13 } 14 } 15 } 16 } 17 } 18 @loige const countdown = createAsyncCountdown(3) for await (const value of countdown) { console.log(value) // 3 ... 2 ... 1 ... 0 } 41
  • 96. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { return { [Symbol.asyncIterator]: function () { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 17 } 18 return { import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 } 17 } 18 [Symbol.asyncIterator]: function () { return { done: false, value: nextVal-- } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 13 } 14 } 15 } 16 } 17 } 18 let nextVal = start import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 [Symbol.asyncIterator]: function () { 5 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 } 17 } 18 @loige const countdown = createAsyncCountdown(3) for await (const value of countdown) { console.log(value) // 3 ... 2 ... 1 ... 0 } 41
  • 97. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { return { [Symbol.asyncIterator]: function () { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 17 } 18 return { import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 } 17 } 18 [Symbol.asyncIterator]: function () { return { done: false, value: nextVal-- } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 13 } 14 } 15 } 16 } 17 } 18 let nextVal = start import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 [Symbol.asyncIterator]: function () { 5 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 } 17 } 18 return { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 15 } 16 } 17 } 18 @loige const countdown = createAsyncCountdown(3) for await (const value of countdown) { console.log(value) // 3 ... 2 ... 1 ... 0 } 41
  • 98. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { return { [Symbol.asyncIterator]: function () { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 17 } 18 return { import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 } 17 } 18 [Symbol.asyncIterator]: function () { return { done: false, value: nextVal-- } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 13 } 14 } 15 } 16 } 17 } 18 let nextVal = start import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 [Symbol.asyncIterator]: function () { 5 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 } 17 } 18 return { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 15 } 16 } 17 } 18 async next () { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 14 } 15 } 16 } 17 } 18 @loige const countdown = createAsyncCountdown(3) for await (const value of countdown) { console.log(value) // 3 ... 2 ... 1 ... 0 } 41
  • 99. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { return { [Symbol.asyncIterator]: function () { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 17 } 18 return { import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 } 17 } 18 [Symbol.asyncIterator]: function () { return { done: false, value: nextVal-- } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 13 } 14 } 15 } 16 } 17 } 18 let nextVal = start import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 [Symbol.asyncIterator]: function () { 5 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 } 17 } 18 return { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 15 } 16 } 17 } 18 async next () { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 14 } 15 } 16 } 17 } 18 await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 9 10 11 12 13 } 14 } 15 } 16 } 17 } 18 @loige const countdown = createAsyncCountdown(3) for await (const value of countdown) { console.log(value) // 3 ... 2 ... 1 ... 0 } 41
  • 100. import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { return { [Symbol.asyncIterator]: function () { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 17 } 18 return { import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 } 17 } 18 [Symbol.asyncIterator]: function () { return { done: false, value: nextVal-- } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 5 let nextVal = start 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 13 } 14 } 15 } 16 } 17 } 18 let nextVal = start import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 [Symbol.asyncIterator]: function () { 5 6 return { 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 } 15 } 16 } 17 } 18 return { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 7 async next () { 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 } 14 15 } 16 } 17 } 18 async next () { } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 8 await setTimeout(delay) 9 if (nextVal < 0) { 10 return { done: true } 11 } 12 return { done: false, value: nextVal-- } 13 14 } 15 } 16 } 17 } 18 await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } import { setTimeout } from 'timers/promises' 1 2 function createAsyncCountdown (start, delay = 1000) { 3 return { 4 [Symbol.asyncIterator]: function () { 5 let nextVal = start 6 return { 7 async next () { 8 9 10 11 12 13 } 14 } 15 } 16 } 17 } 18 import { setTimeout } from 'timers/promises' function createAsyncCountdown (start, delay = 1000) { return { [Symbol.asyncIterator]: function () { let nextVal = start return { async next () { await setTimeout(delay) if (nextVal < 0) { return { done: true } } return { done: false, value: nextVal-- } } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @loige const countdown = createAsyncCountdown(3) for await (const value of countdown) { console.log(value) // 3 ... 2 ... 1 ... 0 } 41
  • 101. import { setTimeout } from 'timers/promises' async function * createAsyncCountdown (start, delay = 1000) { for (let i = start; i >= 0; i--) { await setTimeout(delay) yield i } } 1 2 3 4 5 6 7 8 @loige 42
  • 102. import { setTimeout } from 'timers/promises' async function * createAsyncCountdown (start, delay = 1000) { for (let i = start; i >= 0; i--) { await setTimeout(delay) yield i } } 1 2 3 4 5 6 7 8 async function * createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 for (let i = start; i >= 0; i--) { 4 await setTimeout(delay) 5 yield i 6 } 7 8 @loige const countdown = createAsyncCountdown(3) for await (const value of countdown) { console.log(value) // 3 ... 2 ... 1 ... 0 } 42
  • 103. import { setTimeout } from 'timers/promises' async function * createAsyncCountdown (start, delay = 1000) { for (let i = start; i >= 0; i--) { await setTimeout(delay) yield i } } 1 2 3 4 5 6 7 8 async function * createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 for (let i = start; i >= 0; i--) { 4 await setTimeout(delay) 5 yield i 6 } 7 8 await setTimeout(delay) yield i import { setTimeout } from 'timers/promises' 1 2 async function * createAsyncCountdown (start, delay = 1000) { 3 for (let i = start; i >= 0; i--) { 4 5 6 } 7 } 8 @loige const countdown = createAsyncCountdown(3) for await (const value of countdown) { console.log(value) // 3 ... 2 ... 1 ... 0 } 42
  • 104. import { setTimeout } from 'timers/promises' async function * createAsyncCountdown (start, delay = 1000) { for (let i = start; i >= 0; i--) { await setTimeout(delay) yield i } } 1 2 3 4 5 6 7 8 async function * createAsyncCountdown (start, delay = 1000) { } import { setTimeout } from 'timers/promises' 1 2 3 for (let i = start; i >= 0; i--) { 4 await setTimeout(delay) 5 yield i 6 } 7 8 await setTimeout(delay) yield i import { setTimeout } from 'timers/promises' 1 2 async function * createAsyncCountdown (start, delay = 1000) { 3 for (let i = start; i >= 0; i--) { 4 5 6 } 7 } 8 import { setTimeout } from 'timers/promises' async function * createAsyncCountdown (start, delay = 1000) { for (let i = start; i >= 0; i--) { await setTimeout(delay) yield i } } 1 2 3 4 5 6 7 8 @loige const countdown = createAsyncCountdown(3) for await (const value of countdown) { console.log(value) // 3 ... 2 ... 1 ... 0 } 42
  • 106. When to use async iterators @loige Sequential iteration pattern Data arriving in order over time You need to complete processing the current “chunk” before you can request the next one Examples paginated iteration consuming tasks from a remote queue 44
  • 107. Tips & pitfalls ☠ @loige 45
  • 108. import { createReadStream } from 'fs' const sourceStream = createReadStream('bigdata.csv') let bytes = 0 for await (const chunk of sourceStream) { bytes += chunk.length } console.log(`bigdata.csv: ${bytes} bytes`) 1 2 3 4 5 6 7 8 9 10 @loige Node.js readable streams are async iterators 46
  • 109. import { createReadStream } from 'fs' const sourceStream = createReadStream('bigdata.csv') let bytes = 0 for await (const chunk of sourceStream) { bytes += chunk.length } console.log(`bigdata.csv: ${bytes} bytes`) 1 2 3 4 5 6 7 8 9 10 import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 @loige Node.js readable streams are async iterators 46
  • 110. import { createReadStream } from 'fs' const sourceStream = createReadStream('bigdata.csv') let bytes = 0 for await (const chunk of sourceStream) { bytes += chunk.length } console.log(`bigdata.csv: ${bytes} bytes`) 1 2 3 4 5 6 7 8 9 10 import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 const sourceStream = createReadStream('bigdata.csv') import { createReadStream } from 'fs' 1 2 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 @loige Node.js readable streams are async iterators 46
  • 111. import { createReadStream } from 'fs' const sourceStream = createReadStream('bigdata.csv') let bytes = 0 for await (const chunk of sourceStream) { bytes += chunk.length } console.log(`bigdata.csv: ${bytes} bytes`) 1 2 3 4 5 6 7 8 9 10 import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 const sourceStream = createReadStream('bigdata.csv') import { createReadStream } from 'fs' 1 2 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 let bytes = 0 import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 @loige Node.js readable streams are async iterators 46
  • 112. import { createReadStream } from 'fs' const sourceStream = createReadStream('bigdata.csv') let bytes = 0 for await (const chunk of sourceStream) { bytes += chunk.length } console.log(`bigdata.csv: ${bytes} bytes`) 1 2 3 4 5 6 7 8 9 10 import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 const sourceStream = createReadStream('bigdata.csv') import { createReadStream } from 'fs' 1 2 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 let bytes = 0 import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 for await (const chunk of sourceStream) { } import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 6 bytes += chunk.length 7 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 @loige Node.js readable streams are async iterators 46
  • 113. import { createReadStream } from 'fs' const sourceStream = createReadStream('bigdata.csv') let bytes = 0 for await (const chunk of sourceStream) { bytes += chunk.length } console.log(`bigdata.csv: ${bytes} bytes`) 1 2 3 4 5 6 7 8 9 10 import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 const sourceStream = createReadStream('bigdata.csv') import { createReadStream } from 'fs' 1 2 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 let bytes = 0 import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 for await (const chunk of sourceStream) { } import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 6 bytes += chunk.length 7 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 bytes += chunk.length import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 @loige Node.js readable streams are async iterators 46
  • 114. import { createReadStream } from 'fs' const sourceStream = createReadStream('bigdata.csv') let bytes = 0 for await (const chunk of sourceStream) { bytes += chunk.length } console.log(`bigdata.csv: ${bytes} bytes`) 1 2 3 4 5 6 7 8 9 10 import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 const sourceStream = createReadStream('bigdata.csv') import { createReadStream } from 'fs' 1 2 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 let bytes = 0 import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 for await (const chunk of sourceStream) { } import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 6 bytes += chunk.length 7 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 bytes += chunk.length import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 console.log(`bigdata.csv: ${bytes} bytes`) import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 10 @loige Node.js readable streams are async iterators 46
  • 115. import { createReadStream } from 'fs' const sourceStream = createReadStream('bigdata.csv') let bytes = 0 for await (const chunk of sourceStream) { bytes += chunk.length } console.log(`bigdata.csv: ${bytes} bytes`) 1 2 3 4 5 6 7 8 9 10 import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 const sourceStream = createReadStream('bigdata.csv') import { createReadStream } from 'fs' 1 2 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 let bytes = 0 import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 for await (const chunk of sourceStream) { } import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 6 bytes += chunk.length 7 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 bytes += chunk.length import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 7 } 8 9 console.log(`bigdata.csv: ${bytes} bytes`) 10 console.log(`bigdata.csv: ${bytes} bytes`) import { createReadStream } from 'fs' 1 2 const sourceStream = createReadStream('bigdata.csv') 3 4 let bytes = 0 5 for await (const chunk of sourceStream) { 6 bytes += chunk.length 7 } 8 9 10 import { createReadStream } from 'fs' const sourceStream = createReadStream('bigdata.csv') let bytes = 0 for await (const chunk of sourceStream) { bytes += chunk.length } console.log(`bigdata.csv: ${bytes} bytes`) 1 2 3 4 5 6 7 8 9 10 @loige Node.js readable streams are async iterators 46
  • 117. import { createReadStream } from 'fs' import { once } from 'events' const sourceStream = createReadStream('bigdata.csv') const destStream = new SlowTransform() for await (const chunk of sourceStream) { const canContinue = destStream.write(chunk) if (!canContinue) { // backpressure, now we stop and we need to wait for drain await once(destStream, 'drain') // ok now it's safe to resume writing } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @loige 48
  • 118. import { createReadStream } from 'fs' import { once } from 'events' const sourceStream = createReadStream('bigdata.csv') const destStream = new SlowTransform() for await (const chunk of sourceStream) { const canContinue = destStream.write(chunk) if (!canContinue) { // backpressure, now we stop and we need to wait for drain await once(destStream, 'drain') // ok now it's safe to resume writing } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import { createReadStream } from 'fs' import { once } from 'events' 1 2 3 const sourceStream = createReadStream('bigdata.csv') 4 const destStream = new SlowTransform() 5 6 for await (const chunk of sourceStream) { 7 const canContinue = destStream.write(chunk) 8 if (!canContinue) { 9 // backpressure, now we stop and we need to wait for drain 10 await once(destStream, 'drain') 11 // ok now it's safe to resume writing 12 } 13 } 14 @loige 48
  • 119. import { createReadStream } from 'fs' import { once } from 'events' const sourceStream = createReadStream('bigdata.csv') const destStream = new SlowTransform() for await (const chunk of sourceStream) { const canContinue = destStream.write(chunk) if (!canContinue) { // backpressure, now we stop and we need to wait for drain await once(destStream, 'drain') // ok now it's safe to resume writing } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import { createReadStream } from 'fs' import { once } from 'events' 1 2 3 const sourceStream = createReadStream('bigdata.csv') 4 const destStream = new SlowTransform() 5 6 for await (const chunk of sourceStream) { 7 const canContinue = destStream.write(chunk) 8 if (!canContinue) { 9 // backpressure, now we stop and we need to wait for drain 10 await once(destStream, 'drain') 11 // ok now it's safe to resume writing 12 } 13 } 14 const sourceStream = createReadStream('bigdata.csv') import { createReadStream } from 'fs' 1 import { once } from 'events' 2 3 4 const destStream = new SlowTransform() 5 6 for await (const chunk of sourceStream) { 7 const canContinue = destStream.write(chunk) 8 if (!canContinue) { 9 // backpressure, now we stop and we need to wait for drain 10 await once(destStream, 'drain') 11 // ok now it's safe to resume writing 12 } 13 } 14 @loige 48
  • 120. import { createReadStream } from 'fs' import { once } from 'events' const sourceStream = createReadStream('bigdata.csv') const destStream = new SlowTransform() for await (const chunk of sourceStream) { const canContinue = destStream.write(chunk) if (!canContinue) { // backpressure, now we stop and we need to wait for drain await once(destStream, 'drain') // ok now it's safe to resume writing } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import { createReadStream } from 'fs' import { once } from 'events' 1 2 3 const sourceStream = createReadStream('bigdata.csv') 4 const destStream = new SlowTransform() 5 6 for await (const chunk of sourceStream) { 7 const canContinue = destStream.write(chunk) 8 if (!canContinue) { 9 // backpressure, now we stop and we need to wait for drain 10 await once(destStream, 'drain') 11 // ok now it's safe to resume writing 12 } 13 } 14 const sourceStream = createReadStream('bigdata.csv') import { createReadStream } from 'fs' 1 import { once } from 'events' 2 3 4 const destStream = new SlowTransform() 5 6 for await (const chunk of sourceStream) { 7 const canContinue = destStream.write(chunk) 8 if (!canContinue) { 9 // backpressure, now we stop and we need to wait for drain 10 await once(destStream, 'drain') 11 // ok now it's safe to resume writing 12 } 13 } 14 const destStream = new SlowTransform() import { createReadStream } from 'fs' 1 import { once } from 'events' 2 3 const sourceStream = createReadStream('bigdata.csv') 4 5 6 for await (const chunk of sourceStream) { 7 const canContinue = destStream.write(chunk) 8 if (!canContinue) { 9 // backpressure, now we stop and we need to wait for drain 10 await once(destStream, 'drain') 11 // ok now it's safe to resume writing 12 } 13 } 14 @loige 48
  • 121. import { createReadStream } from 'fs' import { once } from 'events' const sourceStream = createReadStream('bigdata.csv') const destStream = new SlowTransform() for await (const chunk of sourceStream) { const canContinue = destStream.write(chunk) if (!canContinue) { // backpressure, now we stop and we need to wait for drain await once(destStream, 'drain') // ok now it's safe to resume writing } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import { createReadStream } from 'fs' import { once } from 'events' 1 2 3 const sourceStream = createReadStream('bigdata.csv') 4 const destStream = new SlowTransform() 5 6 for await (const chunk of sourceStream) { 7 const canContinue = destStream.write(chunk) 8 if (!canContinue) { 9 // backpressure, now we stop and we need to wait for drain 10 await once(destStream, 'drain') 11 // ok now it's safe to resume writing 12 } 13 } 14 const sourceStream = createReadStream('bigdata.csv') import { createReadStream } from 'fs' 1 import { once } from 'events' 2 3 4 const destStream = new SlowTransform() 5 6 for await (const chunk of sourceStream) { 7 const canContinue = destStream.write(chunk) 8 if (!canContinue) { 9 // backpressure, now we stop and we need to wait for drain 10 await once(destStream, 'drain') 11 // ok now it's safe to resume writing 12 } 13 } 14 const destStream = new SlowTransform() import { createReadStream } from 'fs' 1 import { once } from 'events' 2 3 const sourceStream = createReadStream('bigdata.csv') 4 5 6 for await (const chunk of sourceStream) { 7 const canContinue = destStream.write(chunk) 8 if (!canContinue) { 9 // backpressure, now we stop and we need to wait for drain 10 await once(destStream, 'drain') 11 // ok now it's safe to resume writing 12 } 13 } 14 for await (const chunk of sourceStream) { } import { createReadStream } from 'fs' 1 import { once } from 'events' 2 3 const sourceStream = createReadStream('bigdata.csv') 4 const destStream = new SlowTransform() 5 6 7 const canContinue = destStream.write(chunk) 8 if (!canContinue) { 9 // backpressure, now we stop and we need to wait for drain 10 await once(destStream, 'drain') 11 // ok now it's safe to resume writing 12 } 13 14 @loige 48
  • 122. import { createReadStream } from 'fs' import { once } from 'events' const sourceStream = createReadStream('bigdata.csv') const destStream = new SlowTransform() for await (const chunk of sourceStream) { const canContinue = destStream.write(chunk) if (!canContinue) { // backpressure, now we stop and we need to wait for drain await once(destStream, 'drain') // ok now it's safe to resume writing } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import { createReadStream } from 'fs' import { once } from 'events' 1 2 3 const sourceStream = createReadStream('bigdata.csv') 4 const destStream = new SlowTransform() 5 6 for await (const chunk of sourceStream) { 7 const canContinue = destStream.write(chunk) 8 if (!canContinue) { 9 // backpressure, now we stop and we need to wait for drain 10 await once(destStream, 'drain') 11 // ok now it's safe to resume writing 12 } 13 } 14 const sourceStream = createReadStream('bigdata.csv') import { createReadStream } from 'fs' 1 import { once } from 'events' 2 3 4 const destStream = new SlowTransform() 5 6 for await (const chunk of sourceStream) { 7 const canContinue = destStream.write(chunk) 8 if (!canContinue) { 9 // backpressure, now we stop and we need to wait for drain 10 await once(destStream, 'drain') 11 // ok now it's safe to resume writing 12 } 13 } 14 const destStream = new SlowTransform() import { createReadStream } from 'fs' 1 import { once } from 'events' 2 3 const sourceStream = createReadStream('bigdata.csv') 4 5 6 for await (const chunk of sourceStream) { 7 const canContinue = destStream.write(chunk) 8 if (!canContinue) { 9 // backpressure, now we stop and we need to wait for drain 10 await once(destStream, 'drain') 11 // ok now it's safe to resume writing 12 } 13 } 14 for await (const chunk of sourceStream) { } import { createReadStream } from 'fs' 1 import { once } from 'events' 2 3 const sourceStream = createReadStream('bigdata.csv') 4 const destStream = new SlowTransform() 5 6 7 const canContinue = destStream.write(chunk) 8 if (!canContinue) { 9 // backpressure, now we stop and we need to wait for drain 10 await once(destStream, 'drain') 11 // ok now it's safe to resume writing 12 } 13 14 const canContinue = destStream.write(chunk) import { createReadStream } from 'fs' 1 import { once } from 'events' 2 3 const sourceStream = createReadStream('bigdata.csv') 4 const destStream = new SlowTransform() 5 6 for await (const chunk of sourceStream) { 7 8 if (!canContinue) { 9 // backpressure, now we stop and we need to wait for drain 10 await once(destStream, 'drain') 11 // ok now it's safe to resume writing 12 } 13 } 14 @loige 48