Skip to content

Commit 50af057

Browse files
committed
Added WebSockets example
1 parent a67eb19 commit 50af057

File tree

5 files changed

+144
-0
lines changed

5 files changed

+144
-0
lines changed

5.websockets/app.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const wsConnected = () => ({
2+
type: 'WS_CONNECTED'
3+
});
4+
5+
const wsDisconnected = () => ({
6+
type: 'WS_DISCONNECTED'
7+
});
8+
9+
const chatMessage = (text, global = true) => ({
10+
type: 'CHAT_MESSAGE',
11+
payload: text,
12+
meta: {
13+
websocket: global
14+
}
15+
});
16+
17+
const rootReducer = (state = [], action) => {
18+
switch (action.type) {
19+
case 'CHAT_MESSAGE':
20+
return state.concat({ text: action.payload, meta: action.meta })
21+
}
22+
return state;
23+
};
24+
25+
const store = Redux.createStore(
26+
rootReducer,
27+
Redux.applyMiddleware(logMiddleware, wsMiddleware)
28+
);
29+
30+
$(loadUI);

5.websockets/index.html

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Chapter 5. Websockets with Redux</title>
6+
</head>
7+
<body>
8+
<div id="app"></div>
9+
10+
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script>
11+
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.3.1/redux.min.js"></script>
12+
<script src="middleware.js"></script>
13+
<script src="ui.js"></script>
14+
<script src="app.js"></script>
15+
</body>
16+
</html>

5.websockets/middleware.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
const WS_ROOT = "ws://echo.websocket.org/";
2+
3+
const SOCKET_STATES = {
4+
CONNECTING: 0,
5+
OPEN: 1,
6+
CLOSING: 2,
7+
CLOSED: 3
8+
};
9+
10+
const wsMiddleware = ({ dispatch }) => next => {
11+
12+
const websocket = new WebSocket(WS_ROOT);
13+
14+
Object.assign(websocket, {
15+
onopen() {
16+
active = true;
17+
dispatch(wsConnected())
18+
},
19+
20+
onclose() {
21+
active = false;
22+
dispatch(wsDisconnected())
23+
},
24+
25+
onerror(error) {
26+
console.log(`WS Error: ${ error.data }`);
27+
},
28+
29+
onmessage(event) {
30+
const message = JSON.parse(event.data)
31+
32+
Object.assign(message, { meta: { fromWebsocket: true }});
33+
34+
dispatch(message);
35+
}
36+
});
37+
38+
return action => {
39+
if (websocket.readyState === SOCKET_STATES.OPEN &&
40+
action.meta &&
41+
action.meta.websocket) {
42+
43+
// Remove action metadata before sending
44+
const cleanAction = Object.assign({}, action, {
45+
meta: undefined
46+
});
47+
websocket.send(JSON.stringify(cleanAction));
48+
}
49+
50+
next(action);
51+
};
52+
};
53+
54+
const logMiddleware = ({ getState, dispatch }) => (next) => (action) => {
55+
console.log(`Action: ${ action.type }`, action);
56+
57+
next(action);
58+
};

5.websockets/ui.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const renderMessage = message => `<li>${ message.text } <i>${ JSON.stringify(message.meta) }</i></li>`;
2+
3+
const updateUI = () => {
4+
const messages = store.getState();
5+
6+
$('.messages > ul').html(messages.map(renderMessage));
7+
};
8+
9+
const handleAdd = () => {
10+
const $message = $('.messages > input[type=text]');
11+
const $global = $('.messages > input[type=checkbox]');
12+
13+
store.dispatch(
14+
chatMessage(
15+
$message.val(),
16+
$global.is(':checked')
17+
));
18+
19+
$message.val('');
20+
};
21+
22+
const loadUI = () => {
23+
$('#app').append(`
24+
<div class="messages">
25+
<h2>Websocket messages:</h2>
26+
<ul></ul>
27+
<input type="checkbox" checked />
28+
<label for="">Send to server</label>
29+
<br/>
30+
<input type="text" />
31+
<button>Send</button>
32+
</div>
33+
`);
34+
35+
store.subscribe(updateUI);
36+
37+
$(document).on('click', '.messages > button', handleAdd);
38+
39+
updateUI();
40+
};

chapter5/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)