1 of 37

Interactive frontend development

Urmas Talimaa

SaleMove Inc

2 of 37

Litmus test for libraries/frameworks

  • What are the basic abstractions?
  • How well do they compose?

3 of 37

React/Redux

  • Stateless React components�compose trivially through containment�no state, no gotchas, no complexity
  • Redux reducers�compose trivially through namespacing or plain function composition�pure functions are very simple to compose

4 of 37

React/Redux

  • React-Redux containers �Simple glue
  • Actions�Just names
  • Middleware�Integration with a specific API��

5 of 37

React/Redux

  • New abstractions or small helper functions are easy to write and integrate because the core abstractions are pure functions

(props) => pseudoHtml

(action, previousState) => newState

6 of 37

Why all this functional programming nonsense?

Can’t I just hack things together?

7 of 37

Why all this functional programming nonsense?

In this and next seminars we’ll see how our past design choices can make magic happen.

8 of 37

Middleware

http://redux.js.org/docs/advanced/Middleware.html:

Redux middleware is

...a third-party extension point between dispatching an action, and the moment it reaches the reducer

9 of 37

10 of 37

Middleware

Well suited for mapping updates from a stateful source to actions.

11 of 37

Communication with remote servers

  • Async action creators (and middleware add-ons) allow us to communicate with remote servers using fetch.
  • fetch is unidirectional, cannot make requests from a remote server to a browser.
  • Some web applications might require bidirectional communication to push updates to the browser
    • multiplayer games, chat clients, video chat etc
  • https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API

12 of 37

Long polling?

  • HTTP requests can be hacked to achieve bidirectional communication
  • https://en.wikipedia.org/wiki/Push_technology#Long_polling
    • Client sends request to Server
    • Server keeps connection open (does not respond) until �it has information to push to the Client
    • Client receives response from Server containing the pushed information
    • Client immediately sends a new request to Server, rinse and repeat.
  • All modern Web Browsers support WebSockets which is a saner alternative.
  • Note that simply polling (requesting data with an interval) can still be a valid simplification for many applications.

13 of 37

Websockets

  • The (Browser) Websocket API has the following basic functionality:
    • It can change to be opened when connection between Client and Server is established
      • connection.onopen = callback
    • It can change to be closed when connection is closed by Server or Client or when connection is disrupted
      • connection.onclose = callback
    • It can receive messages from Server
      • connection.onmessage = callback
    • It can send string(utf8) messages to Server
      • connection.send(utf8String)
    • It can be closed
      • connection.close()

A websocket can also send binary messages

14 of 37

Websockets

Websockets (and web requests) are an epitome of mutable state.

You never know what and when is coming from them or what the responses are (if responses arrive at all).

Therefore it’s necessary to put them under tight supervision and not leak them all over our beautiful application code

15 of 37

16 of 37

Testing WebSockets

  • WebSocket connections are initiated using the WebSocket global
  • WebSocket connections are inherently stateful

This make testing WebSockets inconvenient.

There are libraries which provide mock implementations of WebSocket global (https://github.com/thoov/mock-socket)

17 of 37

Testing WebSockets

Luckily we can put the WebSocket connection to a middleware and just map received messages to action creators

This encapsulates all WebSocket related logic, which itself is going to be trivial.

18 of 37

Encapsulating WebSockets using middleware

// Using WebSocket abstraction from basic websocket exampleexport default (store) => (next) => {� let connection = null;� return (action) => {� if (action.type === CONNECT) {� connection = connectToWebSocket({� onOpen: () => store.dispatch(...),� onClose: ({reason}) => store.dispatch(...),� parameters: {...},� onMessage: ({eventName, payload}) => store.dispatch(...)� });� } else if (action.type === DISCONNECT) {� connection.close();� }� return next(action);

};

19 of 37

Distributed systems disclaimer

This is not a course on distributed systems, but...

20 of 37

My advisor on distributed systems

21 of 37

Distributed systems

From the moment a remote Server is introduced, a distributed system is created

In a distributed system it is important to understand

  • who owns (modifies and can be queried for) what information
  • how updates are broadcasted / subscribed to
  • what are the message delivery guarantees of communication channels

22 of 37

Distributed systems

It is very easy to create an inconsistent system.

Difficulting in retaining consistency increases when more moving parts are added to a system (e.g multiple processes for load balancing).

23 of 37

Distributed systems

Before using any technology that can be connected to

  • HTTP requests,
  • WebSockets,
  • (NoSQL, relational) databases,
  • etc

try to read and understand the message delivery and/or consistency guarantees.

24 of 37

WebSocket message delivery guarantees

  • WebSockets use a single TCP connection, messages are guaranteed to arrive in-order and exactly-once (as long as the connection is alive) (https://tools.ietf.org/html/rfc6455)

Obviously not all messages are guaranteed to arrive as connections can be closed.

25 of 37

Game Lobby discussion

Let’s say we add a new feature to the Game Lobby homework application

All players

  • connect to a WebSocket server and
  • receive updates about ongoing games (game status or new moves).
  • are allowed to submit moves to any known game by using the HTTP API.

Detect potential problems in such a design.

Bonus points available for each distinct issue with a coherent explanation.

26 of 37

Object updates with WebSockets

Word of caution from personal experience

When pushing updates about large objects (e.g collections) it can sometimes be a good idea to include a partial update instead of the whole object in the message

27 of 37

Object updates with WebSockets

Instead of

[1,2,3]

[1,2,3,4]

[2,3,4]

28 of 37

Object updates with WebSockets

Server sends Initial: [1,2,3] => Client now has [1,2,3]

Server sends ADD 4 => Client now has [1,2,3,4]

Server sends REMOVE 1 => Client now has [2,3,4]

29 of 37

Object updates with WebSockets

As message order is guaranteed, such updates can be used to maintain an object consistently

30 of 37

Object updates with WebSockets

As message order is guaranteed, such updates can be used to maintain an object consistently

UNLESS

  • A function that handles updates in the client side encounters an error
  • A function that sends updates from the server side encounters an error
  • The update protocol is not re-seeded after connection was dropped and re-initialized.
  • The server does not fully own the object, it is proxied from another source with unknown message delivery guarantees

If anything fails, the maintained object is inconsistent until user refreshes

31 of 37

Object updates with WebSockets

The message order guarantee is only for the single WebSocket connection.

When building any protocol on top of the WebSocket connection this needs to be taken into account.

Try to use something that is battle-tested instead of homebrewing complex protocols on top of the very low level WebSocket API.

Or just send whole objects if you can...

32 of 37

WebSocket request response?

WebSocket is a low level protocol

It does not have request - response semantics

It barely has any semantics at all.

Can we build request-response on top of WebSockets?

33 of 37

WebSocket request response?

If you need it, don’t try to build it yourself

34 of 37

Homework

  • Only submit what is yours

35 of 37

36 of 37

Homework

Final tips

  • Don’t try to solve the homework in the last night. You will not make it.
  • React - Redux are all about simple, reusable components. Make good use of that.
  • Tests are an inseparable part of your homework! Write them first (or at least together with each piece of code).

37 of 37