Taming snakes
with reactive streams
Trainer @thoughtram
twitter.com/elmd_
Slide 2
Slide 2 text
Dominic Elm
ABOUT ME
Slide 3
Slide 3 text
Blogging blog.thoughtram.io
Dominic Elm
ABOUT ME
Trainer @thoughtram
@elmd_
=
Slide 4
Slide 4 text
Blogging blog.thoughtram.io
Dominic Elm
ABOUT ME
Trainer @thoughtram
@elmd_
=
Slide 5
Slide 5 text
• What is reactive programming?
• Why it is important?
• How to think reactively
• Learn common operators and how to accumulate state
• Implementing Snake with RxJS
WHAT TO EXPECT
Slide 6
Slide 6 text
Read the article here
Slide 7
Slide 7 text
WHAT IS REACTIVE?
Reactive programming is programming with
asynchronous data streams.
A stream is a sequence of ongoing events ordered in
time that offer some hooks with which to observe it.
Source: Andre Staltz
Slide 8
Slide 8 text
WHY IS IT IMPORTANT?
Modern web apps are highly
interactive and asynchonous, e.g.
DOM Events
HTTP Requests
Web Sockets
Animations
Server Sent Events
Slide 9
Slide 9 text
WHY IS IT IMPORTANT?
Managing async is hard
Slide 10
Slide 10 text
WHY IS IT IMPORTANT?
How do we deal with such interactive
experience and asynchrony?
Slide 11
Slide 11 text
WHY IS IT IMPORTANT?
How do we deal with such interactive
experience and asynchrony?
Introducing RxJS
Slide 12
Slide 12 text
RxJS brings the concept of functional
reactive programming to the web
Makes it easy to deal with all sorts of synchronous and
asynchronous data streams
Introduces Observable type to represent data streams
Observables are…
Composable
Proxies for values
Single or Multiple Values
First-class objects
Immutable
Lazy
Cancelable
Slide 15
Slide 15 text
Observables are…
Composable
Proxies for values
Single or Multiple Values
First-class objects
Immutable
Lazy
Cancelable
Slide 16
Slide 16 text
Let’s learn how to think
reactively
Slide 17
Slide 17 text
THE GAME
Slide 18
Slide 18 text
OUR GOALS
• Re-implement Snake
• Only use HTML5, JavaScript and RxJS
• Transform programatic event-loop (imperative) into a
reactive-event driven app
• NO external state outside the observable pipeline
Slide 19
Slide 19 text
Modifying state that is visible to
other functions
=
Side Effect
let keydown$ = fromEvent(document, 'keydown');
let direction$ = keydown$.pipe(
map((event: KeyboardEvent) => DIRECTIONS[event.keyCode]),
filter(direction => !!direction),
startWith(INITIAL_DIRECTION),
scan(nextDirection),
distinctUntilChanged()
);
Slide 37
Slide 37 text
let keydown$ = fromEvent(document, 'keydown');
let direction$ = keydown$.pipe(
map((event: KeyboardEvent) => DIRECTIONS[event.keyCode]),
filter(direction => !!direction),
startWith(INITIAL_DIRECTION),
scan(nextDirection),
distinctUntilChanged()
);
DIRECTIONS is a key/value map for all possible directions, e.g. DIRECTIONS[39] = { x: 1, y: 0 }
Slide 38
Slide 38 text
let keydown$ = fromEvent(document, 'keydown');
let direction$ = keydown$.pipe(
map((event: KeyboardEvent) => DIRECTIONS[event.keyCode]),
filter(direction => !!direction),
startWith(INITIAL_DIRECTION),
scan(nextDirection),
distinctUntilChanged()
);
Slide 39
Slide 39 text
let keydown$ = fromEvent(document, 'keydown');
let direction$ = keydown$.pipe(
map((event: KeyboardEvent) => DIRECTIONS[event.keyCode]),
filter(direction => !!direction),
startWith(INITIAL_DIRECTION),
scan(nextDirection),
distinctUntilChanged()
);
Slide 40
Slide 40 text
let keydown$ = fromEvent(document, 'keydown');
let direction$ = keydown$.pipe(
map((event: KeyboardEvent) => DIRECTIONS[event.keyCode]),
filter(direction => !!direction),
startWith(INITIAL_DIRECTION),
scan(nextDirection),
distinctUntilChanged()
);
Slide 41
Slide 41 text
let keydown$ = fromEvent(document, 'keydown');
let direction$ = keydown$.pipe(
map((event: KeyboardEvent) => DIRECTIONS[event.keyCode]),
filter(direction => !!direction),
startWith(INITIAL_DIRECTION),
scan(nextDirection),
distinctUntilChanged()
);
Slide 42
Slide 42 text
BUILDING BLOCKS
• Steering mechanism
• Player’s score
• Snake
• Apples
Slide 43
Slide 43 text
PLAYER SCORE
snake$ apples$
[{…}, {…}, {…}] [{…}, {…}, {…}]