SlideShare a Scribd company logo
Building Real-Time Apps with
EmberJS & WebSockets
Ben LimmerGEMConf - 5/21/2016 ember.party
blimmer
Ben LimmerEmberJS Meetup - 2/24/2016 ember.party
♥
Ben LimmerGEMConf - 5/21/2016 ember.party
Talk Roadmap
• WebSockets vs. AJAX
• Fundamentals of WebSockets
• Code!
• Other Considerations
Ben LimmerGEMConf - 5/21/2016 ember.party
request
response
request
response
AJAX
Ben LimmerGEMConf - 5/21/2016 ember.party
with a lot of apps, this
paradigm still works
Ben LimmerGEMConf - 5/21/2016 ember.party
but what about
real-time apps?
Ben LimmerGEMConf - 5/21/2016 ember.party
e.g.
Ben LimmerGEMConf - 5/21/2016 ember.party
live dashboards
Ben LimmerGEMConf - 5/21/2016 ember.party
Source: http://www.heckyl.com/
Ben LimmerGEMConf - 5/21/2016 ember.party
2nd screen apps
Ben LimmerGEMConf - 5/21/2016 ember.party© MLB / Source: MLB.com
Ben LimmerGEMConf - 5/21/2016 ember.party
deployment
notifications
Ben LimmerGEMConf - 5/21/2016 ember.party
Source: inbox.google.com
Ben LimmerGEMConf - 5/21/2016 ember.party
games
Ben LimmerGEMConf - 5/21/2016 ember.party
Source: http://browserquest.mozilla.org/img/common/promo-title.jpg
Ben LimmerGEMConf - 5/21/2016 ember.party
chat
gamesdeployment
notifications
live dashboards
2nd screen
apps
activity
streams
comment
sections
realtime
progress
collaborative
editing
Ben LimmerGEMConf - 5/21/2016 ember.party
how do we build a
real-time app?
Ben LimmerGEMConf - 5/21/2016 ember.party
update?
nope.
(old way)
short polling
update?
nope.
data
update?
yep!
Ben LimmerGEMConf - 5/21/2016 ember.party
(old way)
long polling
request
Keep-Alive
timeout
request
Keep-Alive
data
response
request
Keep-Alive
Ben LimmerGEMConf - 5/21/2016 ember.party
WebSockets
handshake
connection opened
bi-directional
communication
Ben LimmerGEMConf - 5/21/2016 ember.party
WebSockets
no polling
full duplex over TCP
communication over
standard HTTP(S) ports
broadcast to all
connected clients
Ben LimmerGEMConf - 5/21/2016 ember.party
Talk Roadmap
• WebSockets vs. AJAX
• Fundamentals of WebSockets
• Code!
• Other Considerations
Ben LimmerGEMConf - 5/21/2016 ember.party
the handshake
Ben LimmerGEMConf - 5/21/2016 ember.party
Request
GET wss://example.org/socket HTTP/1.1
Origin: https://example.org
Host: example.org
Sec-WebSocket-Key: zy6Dy9mSAIM7GJZNf9rI1A==
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Response
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Sec-WebSocket-Accept: EDJa7WCAQQzMCYNJM42Syuo9SqQ=
Upgrade: websocket
events
• open
• message
• error
• close
• send
• close
methods
Ben LimmerGEMConf - 5/21/2016 ember.party
WebSocket.send()
Ben LimmerGEMConf - 5/21/2016 ember.party
send(String 'foo');
send(Blob 010101);
send(ArrayBuffer file);
Ben LimmerGEMConf - 5/21/2016 ember.party
WebSocket.send(’YOLO’);
Ben LimmerGEMConf - 5/21/2016 ember.party
sub-protocols
• a contract between client/server
• 2 classes of sub-protocols
• well-defined (e.g. STOMP, WAMP)
• application specific protocols
Ben LimmerGEMConf - 5/21/2016 ember.party
Request with Protocol
GET wss://example.org/socket HTTP/1.1
Origin: https://example.org
Host: example.org
Sec-WebSocket-Key: zy6Dy9mSAIM7GJZNf9rI1A==
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Protocol: v10.stomp
Ben LimmerGEMConf - 5/21/2016 ember.party
STOMP
SEND
destination:/queue/a
hello queue a
^@
MESSAGE
destination:/queue/a
message-id: <message-identifier>
hello queue a
^@
Ben LimmerGEMConf - 5/21/2016 ember.party
STOMP
SEND
destination:/queue/a
hello queue a
^@
Ben LimmerGEMConf - 5/21/2016 ember.party
subprotocols bring
structure to ws
Ben LimmerGEMConf - 5/21/2016 ember.party
Talk Roadmap
• AJAX vs. WebSockets
• Fundamentals of WebSockets
• Code!
• Other Considerations
Ben LimmerGEMConf - 5/21/2016 ember.party
let’s build something!
Ben LimmerGEMConf - 5/21/2016 ember.party
Ben LimmerEmberJS Meetup - 2/24/2016 ember.party
alice clicks
bob / everyone
sees
Ben LimmerEmberJS Meetup - 2/24/2016 ember.party
bob clicks
alice / everyone
sees
Ben LimmerGEMConf - 5/21/2016 ember.party
npm install ws
Ben LimmerGEMConf - 5/21/2016 ember.party
Ben LimmerGEMConf - 5/21/2016 ember.party
• fast
• simple WebSocket implementation
• few bells and whistles
npm install ws
Ben LimmerGEMConf - 5/21/2016 ember.party
server/index.js
1 const WebSocketServer = require('ws').Server;
2
3 const wss = new WebSocketServer({
4 port: process.env.PORT
5 });
Ben LimmerGEMConf - 5/21/2016 ember.party
waiting for socket
connection…
Ben LimmerGEMConf - 5/21/2016 ember.party
ember install ember-websockets
Ben LimmerGEMConf - 5/21/2016 ember.party
Ben LimmerGEMConf - 5/21/2016 ember.party
ember install ember-websockets
• integrates with the Ember runloop
• is an Ember.ObjectProxy
• abstracts away the WebSocket
Ben LimmerGEMConf - 5/21/2016 ember.party
app/services/rt-ember-socket.js
1 websockets: service(),
2
3 init() {
4 this._super(...arguments);
5
6 const socket = this.get('websockets').socketFor(host);
7
8 socket.on('open', this.open, this);
9 socket.on('close', this.reconnect, this);
10 },
11
12 online: false,
13 open() {
14 this.set('online', true);
15 },
16
17 reconnect() {
18 this.set('online', false);
19
20 Ember.run.later(this, () => {
21 this.get('socket').reconnect();
22 }, 5000);
23 },
Ben LimmerGEMConf - 5/21/2016 ember.party
Ben LimmerGEMConf - 5/21/2016 ember.party
rtember-1.0 - sub-protocol
Ben LimmerGEMConf - 5/21/2016 ember.party
rtember-1.0 - sub-protocol
data events
Ben LimmerGEMConf - 5/21/2016 ember.party
server/index.js
1 const WebSocketServer = require('ws').Server;
2
3 const wss = new WebSocketServer({
4 port: process.env.PORT,
5 handleProtocols: function(protocol, cb) {
6 const supportedProtocol =
7 protocol[protocol.indexOf('rtember-1.0')];
8 if (supportedProtocol) {
9 cb(true, supportedProtocol);
10 } else {
11 cb(false);
12 }
13 },
14 });
Ben LimmerGEMConf - 5/21/2016 ember.party
Ben LimmerGEMConf - 5/21/2016 ember.party
app/services/rt-ember-socket.js
1 websockets: Ember.inject.service(),
2
3 socket: null,
4 init() {
5 this._super(...arguments);
6
7 const socket = this.get('websockets')
8 .socketFor(host, ['rtember-1.0']);
9
10 socket.on('open', this.open, this);
11 socket.on('close', this.reconnect, this);
12
13 this.set('socket', socket);
14 },
Ben LimmerGEMConf - 5/21/2016 ember.party
Ben LimmerGEMConf - 5/21/2016 ember.party
rtember-1.0 - sub-protocol
data events
Ben LimmerGEMConf - 5/21/2016 ember.party
rtember-1.0 - sub-protocol
{
"frameType": "event",
"payload": {
“eventType": ... event type ...,
"eventInfo": ... event info ...
}
}
{
"frameType": "data",
"payload": {
... json api payload ...
}
}
or
Ben LimmerGEMConf - 5/21/2016 ember.party
rtember-1.0 - sub-protocol
data events
Ben LimmerGEMConf - 5/21/2016 ember.party
1 wss.on('connection', function(ws) {
2 sendInitialGifs(ws);
3 });
4
5 function sendInitialGifs(ws) {
6 const gifs = gifDb;
7 const random = _.sampleSize(gifs, 25);
8
9 sendDataToClient(ws, serializeGifs(random));
10 }
11
12 function sendDataToClient(ws, payload) {
13 const payload = {
14 frameType: FRAME_TYPES.DATA,
15 payload,
16 }
17 ws.send(JSON.stringify(payload));
18 }
Ben LimmerGEMConf - 5/21/2016 ember.party
app/services/rt-ember-socket.js
1 init() {
2 ...
3 socket.on('message', this.handleMessage, this);
4 ...
5 },
6
7 handleMessage(msg) {
8 const { frameType, payload } = JSON.parse(msg.data);
9
10 if (frameType === FRAME_TYPES.DATA) {
11 this.handleData(payload);
12 } else {
13 warn(`Encountered unknown frame type: ${frameType}`);
14 }
15 },
16
17 handleData(payload) {
18 this.get('store').pushPayload(payload);
19 }
Ben LimmerGEMConf - 5/21/2016 ember.party
Ben LimmerGEMConf - 5/21/2016 ember.party
{
"frameType": "data",
"payload": {
"data": [{
"type": "gif",
"id": "3o8doPV2heuYjdN2Fy",
"attributes": {
"url": "http://giphy.com/3o8doPV2heuYjdN2Fy/giphy.gif"
}
}, { ... }, { ... }]
}
}
Ben LimmerGEMConf - 5/21/2016 ember.party
Ben LimmerGEMConf - 5/21/2016 ember.party
app/routes/index.js
1 export default Ember.Route.extend({
2 model() {
3 return this.store.peekAll('gif');
4 }
5 });
Ben LimmerGEMConf - 5/21/2016 ember.party
Ben LimmerGEMConf - 5/21/2016 ember.party
app/templates/index.hbs
{{gif-tv gifs=model}}
app/templates/components/gif-tv.hbs
<div class='suggestions'>
{{#each gifs as |gif|}}
<img src={{gif.url}} />
{{/each}}
</div>
Ben LimmerGEMConf - 5/21/2016 ember.party
Ben LimmerGEMConf - 5/21/2016 ember.party
Ben LimmerGEMConf - 5/21/2016 ember.party
rtember-1.0 - sub-protocol
data events
Ben LimmerGEMConf - 5/21/2016 ember.party
rtember-1.0 - sub-protocol
{
"frameType": "event",
"payload": {
“eventType": ... event type ...,
"eventInfo": ... event info ...
}
}
Ben LimmerGEMConf - 5/21/2016 ember.party
Share GIF Event
{
"frameType": "event",
"payload": {
"eventType": "share_gif",
"eventInfo": "<gif_id>"
}
}
{
"frameType": "data",
"payload": {[
<shared_gif>,
<previously_shared_gif>
]}
}
Ben LimmerGEMConf - 5/21/2016 ember.party
{
"frameType": "data",
"payload": {
"data": [
{
"type": "gifs",
"id": "3o8doPV2heuYjdN2Fy",
"attributes": {
"url": "http://giphy.com/3o8doPV2heuYjdN2Fy/giphy.gif",
"shared": false
}
},
{
"type": "gifs",
"id": "xTiQyBOIQe5cgiyUPS",
"attributes": {
"url": "http://giphy.com/xTiQyBOIQe5cgiyUPS/giphy.gif",
"shared": true
}
}
]
}
}
Ben LimmerGEMConf - 5/21/2016 ember.party
app/templates/components/gif-tv.hbs
<div class='suggestions'>
{{#each gifs as |gif|}}
<img {{action shareGif gif}} src={{gif.url}} />
{{/each}}
</div>
app/components/gif-tv.js
1 export default Ember.Component.extend({
2 rtEmberSocket: service(),
3
4 shareGif(gif) {
5 this.get('rtEmberSocket')
6 .sendEvent(EVENTS.SHARE_GIF, gif.get('id'));
7 },
8 });
Ben LimmerGEMConf - 5/21/2016 ember.party
6 .sendEvent(EVENTS.SHARE_GIF, gif.get('id'));
7 },
8 });
app/services/rt-ember-socket.js
1 sendEvent(eventType, eventInfo) {
2 this.get('socket').send(JSON.stringify({
3 frameType: FRAME_TYPES.EVENT,
4 payload: {
5 eventType,
6 eventInfo,
7 },
8 }));
9 }
Ben LimmerEmberJS Meetup - 2/24/2016 ember.party
1 ws.on('message', function(rawData) {
2 const data = JSON.parse(rawData);
3
4 if (data.frameType === FRAME_TYPES.EVENT) {
5 const newShare = _.find(gifDb, {
6 id: data.payload.eventInfo
7 });
8 const previouslyShared = _.find(gifDb, 'shared');
9
10 newShare.shared = true;
11 previouslyShared.shared = false;
12
13 const framePayload = {
14 frameType: FRAME_TYPES.DATA,
15 payload: serializeGifs([previouslyShared, newShare]),
16 };
17 const rawPayload = JSON.stringify(framePayload);
18 wss.clients.forEach((client) => {
19 client.send(rawPayload);
20 });
21 }
22 });
Ben LimmerGEMConf - 5/21/2016 ember.party
beware
Ben LimmerGEMConf - 5/21/2016 ember.party
1 ws.on('message', function(rawData) {
2 try {
3 const data = JSON.parse(rawData);
4
5 if (data.frameType === FRAME_TYPES.EVENT) {
6 if (data.payload.eventType !== EVENTS.SHARE_GIF) {
7 throw Error(); // unknown event
8 }
9
10 const newShare = ...;
11 if (!newShare) {
12 throw Error(); // unknown gif
13 }
14 ...
15 }
16 } catch(e) {
17 ws.close(1003); // unsupported data
18 }
19 });
Ben LimmerGEMConf - 5/21/2016 ember.party
{
"frameType": "data",
"payload": {
"data": [
{
"type": "gifs",
"id": "3o8doPV2heuYjdN2Fy",
"attributes": {
"url": "http://giphy.com/3o8doPV2heuYjdN2Fy/giphy.gif",
"shared": false
}
},
{
"type": "gifs",
"id": "xTiQyBOIQe5cgiyUPS",
"attributes": {
"url": "http://giphy.com/xTiQyBOIQe5cgiyUPS/giphy.gif",
"shared": true
}
}
]
}
}
Ben LimmerGEMConf - 5/21/2016 ember.party
app/templates/components/gif-tv.hbs
app/components/gif-tv.js
1 export default Ember.Component.extend({
2 sharedGif: computed('gifs.@each.shared', function() {
3 return this.get('gifs').findBy('shared', true);
4 }),
5 });
<div class='shared-gif'>
<img src={{sharedGif.url}} />
</div>
<div class='suggestions'>
<!-- ... -->
</div>
Ben LimmerGEMConf - 5/21/2016 ember.party
Ben LimmerGEMConf - 5/21/2016 ember.party
ember.party/gemconf
Ben LimmerGEMConf - 5/21/2016 ember.party
Ben LimmerGEMConf - 5/21/2016 ember.party
Talk Roadmap
• AJAX vs. WebSockets
• Fundamentals of WebSockets
• Code!
• Other Considerations
Ben LimmerGEMConf - 5/21/2016 ember.party
other considerations
• security
• websocket support (libraries)
• learn from example
Ben LimmerGEMConf - 5/21/2016 ember.party
security
• Use TLS (wss:// vs. ws://)
• Verify the Origin header
• Verify the request by using a random token on
handshake
source: WebSocket (Andrew Lombardi) - O’Reilly
Ben LimmerGEMConf - 5/21/2016 ember.party
other considerations
• security
• websocket support (libraries)
• learn from example
Ben LimmerGEMConf - 5/21/2016 ember.party
support
Ben LimmerGEMConf - 5/21/2016 ember.party
9
Ben LimmerGEMConf - 5/21/2016 ember.party
socket.io
• Graceful fallback to polling / flash (!)
• Syntactic Sugar vs. ws package
• Support in ember-websockets add-on
Ben LimmerGEMConf - 5/21/2016 ember.party
Ben LimmerGEMConf - 5/21/2016 ember.party
pusher.com
• Graceful fallback
• Presence support
• Authentication / Security strategies
• No infrastructure required
Ben LimmerGEMConf - 5/21/2016 ember.party
other considerations
• security
• websocket support (libraries)
• learn from example
Ben LimmerGEMConf - 5/21/2016 ember.party
learn by example
Ben LimmerGEMConf - 5/21/2016 ember.party
learn by example
Ben LimmerGEMConf - 5/21/2016 ember.party
https://github.com/blimmer/real-time-ember-client
https://github.com/blimmer/real-time-ember-server
l1m5blimmer
Ben LimmerGEMConf - 5/21/2016 ember.party
thanks!
• WebSocket: Lightweight Client-Server
Communications (O’Reilly)
• WebSockets: Methods for Real-Time Data
Streaming (Steve Schwartz)
Credits
• pusher.com
• socket.io
• node ws
• websocket security (heroku)
Resources

More Related Content

What's hot

mise en place de wordpresss sous Ubuntu 22.04
mise en place de wordpresss sous Ubuntu 22.04mise en place de wordpresss sous Ubuntu 22.04
mise en place de wordpresss sous Ubuntu 22.04
ImnaTech
 
History of L0phtCrack
History of L0phtCrackHistory of L0phtCrack
History of L0phtCrack
cwysopal
 
JAMES WEBB SPACE TELESCOPE
JAMES WEBB SPACE TELESCOPEJAMES WEBB SPACE TELESCOPE
JAMES WEBB SPACE TELESCOPE
Sreeja Nettath
 
Spnego configuration
Spnego configurationSpnego configuration
Spnego configuration
Gabriella Davis
 
Artemis mission
Artemis missionArtemis mission
Artemis mission
Saloni Bhatia
 
Deskpool making vdi cost effective for smb
Deskpool making vdi cost effective for smbDeskpool making vdi cost effective for smb
Deskpool making vdi cost effective for smb
DongLiwu
 
The View - Lotusscript coding best practices
The View - Lotusscript coding best practicesThe View - Lotusscript coding best practices
The View - Lotusscript coding best practicesBill Buchan
 
June OpenNTF Webinar - Domino V12 Certification Manager
June OpenNTF Webinar - Domino V12 Certification ManagerJune OpenNTF Webinar - Domino V12 Certification Manager
June OpenNTF Webinar - Domino V12 Certification Manager
Howard Greenberg
 
08 04 mise en place d'un serveur mandataire (proxy)
08 04 mise en place d'un serveur mandataire (proxy)08 04 mise en place d'un serveur mandataire (proxy)
08 04 mise en place d'un serveur mandataire (proxy)
Noël
 
IBM Traveler Management, Security and Performance
IBM Traveler Management, Security and PerformanceIBM Traveler Management, Security and Performance
IBM Traveler Management, Security and Performance
Gabriella Davis
 

What's hot (10)

mise en place de wordpresss sous Ubuntu 22.04
mise en place de wordpresss sous Ubuntu 22.04mise en place de wordpresss sous Ubuntu 22.04
mise en place de wordpresss sous Ubuntu 22.04
 
History of L0phtCrack
History of L0phtCrackHistory of L0phtCrack
History of L0phtCrack
 
JAMES WEBB SPACE TELESCOPE
JAMES WEBB SPACE TELESCOPEJAMES WEBB SPACE TELESCOPE
JAMES WEBB SPACE TELESCOPE
 
Spnego configuration
Spnego configurationSpnego configuration
Spnego configuration
 
Artemis mission
Artemis missionArtemis mission
Artemis mission
 
Deskpool making vdi cost effective for smb
Deskpool making vdi cost effective for smbDeskpool making vdi cost effective for smb
Deskpool making vdi cost effective for smb
 
The View - Lotusscript coding best practices
The View - Lotusscript coding best practicesThe View - Lotusscript coding best practices
The View - Lotusscript coding best practices
 
June OpenNTF Webinar - Domino V12 Certification Manager
June OpenNTF Webinar - Domino V12 Certification ManagerJune OpenNTF Webinar - Domino V12 Certification Manager
June OpenNTF Webinar - Domino V12 Certification Manager
 
08 04 mise en place d'un serveur mandataire (proxy)
08 04 mise en place d'un serveur mandataire (proxy)08 04 mise en place d'un serveur mandataire (proxy)
08 04 mise en place d'un serveur mandataire (proxy)
 
IBM Traveler Management, Security and Performance
IBM Traveler Management, Security and PerformanceIBM Traveler Management, Security and Performance
IBM Traveler Management, Security and Performance
 

Viewers also liked

Ember and WebSockets
Ember and WebSocketsEmber and WebSockets
Ember and WebSockets
Steve Kinney
 
Ember js meetup treviso liquid-fire
Ember js meetup treviso liquid-fireEmber js meetup treviso liquid-fire
Ember js meetup treviso liquid-fire
William Bergamo
 
HTML5 Websockets and Java - Arun Gupta
HTML5 Websockets and Java - Arun GuptaHTML5 Websockets and Java - Arun Gupta
HTML5 Websockets and Java - Arun Gupta
JAX London
 
Real-Time Web Apps in 2015 & Beyond
Real-Time Web Apps in 2015 & BeyondReal-Time Web Apps in 2015 & Beyond
Real-Time Web Apps in 2015 & Beyond
Phil Leggetter
 
Ember.js internals backburner.js and rsvp.js
Ember.js internals  backburner.js and rsvp.jsEmber.js internals  backburner.js and rsvp.js
Ember.js internals backburner.js and rsvp.jsgavinjoyce
 
Parse Apps with Ember.js
Parse Apps with Ember.jsParse Apps with Ember.js
Parse Apps with Ember.js
Matthew Beale
 
Facebook UI Evolution
Facebook UI EvolutionFacebook UI Evolution
Facebook UI Evolution
Christian Happel
 
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over WebsocketIntroduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
sametmax
 

Viewers also liked (8)

Ember and WebSockets
Ember and WebSocketsEmber and WebSockets
Ember and WebSockets
 
Ember js meetup treviso liquid-fire
Ember js meetup treviso liquid-fireEmber js meetup treviso liquid-fire
Ember js meetup treviso liquid-fire
 
HTML5 Websockets and Java - Arun Gupta
HTML5 Websockets and Java - Arun GuptaHTML5 Websockets and Java - Arun Gupta
HTML5 Websockets and Java - Arun Gupta
 
Real-Time Web Apps in 2015 & Beyond
Real-Time Web Apps in 2015 & BeyondReal-Time Web Apps in 2015 & Beyond
Real-Time Web Apps in 2015 & Beyond
 
Ember.js internals backburner.js and rsvp.js
Ember.js internals  backburner.js and rsvp.jsEmber.js internals  backburner.js and rsvp.js
Ember.js internals backburner.js and rsvp.js
 
Parse Apps with Ember.js
Parse Apps with Ember.jsParse Apps with Ember.js
Parse Apps with Ember.js
 
Facebook UI Evolution
Facebook UI EvolutionFacebook UI Evolution
Facebook UI Evolution
 
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over WebsocketIntroduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
Introduction to WAMP, a protocol enabling PUB/SUB and RPC over Websocket
 

Similar to Building Realtime Apps with Ember.js and WebSockets

Going Live! with Comet
Going Live! with CometGoing Live! with Comet
Going Live! with Comet
Simon Willison
 
Hitchhiker's guide to the front end development
Hitchhiker's guide to the front end developmentHitchhiker's guide to the front end development
Hitchhiker's guide to the front end development
정윤 김
 
Top-5-production-devconMunich-2023.pptx
Top-5-production-devconMunich-2023.pptxTop-5-production-devconMunich-2023.pptx
Top-5-production-devconMunich-2023.pptx
Tier1 app
 
The curious case of misrendered JSON
The curious case of misrendered JSONThe curious case of misrendered JSON
The curious case of misrendered JSON
Jakub Wadolowski
 
Top-5-Performance-JaxLondon-2023.pptx
Top-5-Performance-JaxLondon-2023.pptxTop-5-Performance-JaxLondon-2023.pptx
Top-5-Performance-JaxLondon-2023.pptx
Tier1 app
 
Socket.io
Socket.ioSocket.io
Socket.io
Diego Pacheco
 
WPE WebKit for Android
WPE WebKit for AndroidWPE WebKit for Android
WPE WebKit for Android
Igalia
 
Time for Comet?
Time for Comet?Time for Comet?
Time for Comet?
Simon Willison
 
스트리밍과 디지털 권리 관리
스트리밍과 디지털 권리 관리스트리밍과 디지털 권리 관리
스트리밍과 디지털 권리 관리
우영 주
 
WebSocket JSON Hackday
WebSocket JSON HackdayWebSocket JSON Hackday
WebSocket JSON HackdaySomay Nakhal
 
itjsbagg410
itjsbagg410itjsbagg410
itjsbagg410
Kati Long
 
The HTML5 WebSocket API
The HTML5 WebSocket APIThe HTML5 WebSocket API
The HTML5 WebSocket API
David Lindkvist
 
Comet from JavaOne 2008
Comet from JavaOne 2008Comet from JavaOne 2008
Comet from JavaOne 2008
Joe Walker
 
Bfg Ploneconf Oct2008
Bfg Ploneconf Oct2008Bfg Ploneconf Oct2008
Bfg Ploneconf Oct2008Jeffrey Clark
 
Analyzing the Performance of Mobile Web
Analyzing the Performance of Mobile WebAnalyzing the Performance of Mobile Web
Analyzing the Performance of Mobile Web
Ariya Hidayat
 
IE 8 et les standards du Web - Chris Wilson - Paris Web 2008
IE 8 et les standards du Web - Chris Wilson - Paris Web 2008IE 8 et les standards du Web - Chris Wilson - Paris Web 2008
IE 8 et les standards du Web - Chris Wilson - Paris Web 2008
Association Paris-Web
 
Web Leaps Forward
Web Leaps ForwardWeb Leaps Forward
Web Leaps Forward
Moh Haghighat
 
Consuming GRIN GLOBAL Webservices
Consuming GRIN GLOBAL WebservicesConsuming GRIN GLOBAL Webservices
Consuming GRIN GLOBAL Webservices
Edwin Rojas
 
WebRTC: A front-end perspective
WebRTC: A front-end perspectiveWebRTC: A front-end perspective
WebRTC: A front-end perspective
shwetank
 
"Hidden difficulties of debugger implementation for .NET WASM apps", Andrii R...
"Hidden difficulties of debugger implementation for .NET WASM apps", Andrii R..."Hidden difficulties of debugger implementation for .NET WASM apps", Andrii R...
"Hidden difficulties of debugger implementation for .NET WASM apps", Andrii R...
Fwdays
 

Similar to Building Realtime Apps with Ember.js and WebSockets (20)

Going Live! with Comet
Going Live! with CometGoing Live! with Comet
Going Live! with Comet
 
Hitchhiker's guide to the front end development
Hitchhiker's guide to the front end developmentHitchhiker's guide to the front end development
Hitchhiker's guide to the front end development
 
Top-5-production-devconMunich-2023.pptx
Top-5-production-devconMunich-2023.pptxTop-5-production-devconMunich-2023.pptx
Top-5-production-devconMunich-2023.pptx
 
The curious case of misrendered JSON
The curious case of misrendered JSONThe curious case of misrendered JSON
The curious case of misrendered JSON
 
Top-5-Performance-JaxLondon-2023.pptx
Top-5-Performance-JaxLondon-2023.pptxTop-5-Performance-JaxLondon-2023.pptx
Top-5-Performance-JaxLondon-2023.pptx
 
Socket.io
Socket.ioSocket.io
Socket.io
 
WPE WebKit for Android
WPE WebKit for AndroidWPE WebKit for Android
WPE WebKit for Android
 
Time for Comet?
Time for Comet?Time for Comet?
Time for Comet?
 
스트리밍과 디지털 권리 관리
스트리밍과 디지털 권리 관리스트리밍과 디지털 권리 관리
스트리밍과 디지털 권리 관리
 
WebSocket JSON Hackday
WebSocket JSON HackdayWebSocket JSON Hackday
WebSocket JSON Hackday
 
itjsbagg410
itjsbagg410itjsbagg410
itjsbagg410
 
The HTML5 WebSocket API
The HTML5 WebSocket APIThe HTML5 WebSocket API
The HTML5 WebSocket API
 
Comet from JavaOne 2008
Comet from JavaOne 2008Comet from JavaOne 2008
Comet from JavaOne 2008
 
Bfg Ploneconf Oct2008
Bfg Ploneconf Oct2008Bfg Ploneconf Oct2008
Bfg Ploneconf Oct2008
 
Analyzing the Performance of Mobile Web
Analyzing the Performance of Mobile WebAnalyzing the Performance of Mobile Web
Analyzing the Performance of Mobile Web
 
IE 8 et les standards du Web - Chris Wilson - Paris Web 2008
IE 8 et les standards du Web - Chris Wilson - Paris Web 2008IE 8 et les standards du Web - Chris Wilson - Paris Web 2008
IE 8 et les standards du Web - Chris Wilson - Paris Web 2008
 
Web Leaps Forward
Web Leaps ForwardWeb Leaps Forward
Web Leaps Forward
 
Consuming GRIN GLOBAL Webservices
Consuming GRIN GLOBAL WebservicesConsuming GRIN GLOBAL Webservices
Consuming GRIN GLOBAL Webservices
 
WebRTC: A front-end perspective
WebRTC: A front-end perspectiveWebRTC: A front-end perspective
WebRTC: A front-end perspective
 
"Hidden difficulties of debugger implementation for .NET WASM apps", Andrii R...
"Hidden difficulties of debugger implementation for .NET WASM apps", Andrii R..."Hidden difficulties of debugger implementation for .NET WASM apps", Andrii R...
"Hidden difficulties of debugger implementation for .NET WASM apps", Andrii R...
 

More from Ben Limmer

Tips & Tricks for Being a Successful Tech Lead
Tips & Tricks for Being a Successful Tech LeadTips & Tricks for Being a Successful Tech Lead
Tips & Tricks for Being a Successful Tech Lead
Ben Limmer
 
1-Up Your Git Skills
1-Up Your Git Skills1-Up Your Git Skills
1-Up Your Git Skills
Ben Limmer
 
Maximize your output (sans productivity shame)
Maximize your output (sans productivity shame)Maximize your output (sans productivity shame)
Maximize your output (sans productivity shame)
Ben Limmer
 
[OLD] Understanding Github PR Merge Options (1up-ing your git skills part 2)
[OLD] Understanding Github PR Merge Options (1up-ing your git skills part 2)[OLD] Understanding Github PR Merge Options (1up-ing your git skills part 2)
[OLD] Understanding Github PR Merge Options (1up-ing your git skills part 2)
Ben Limmer
 
Upgrading Ember.js Apps
Upgrading Ember.js AppsUpgrading Ember.js Apps
Upgrading Ember.js Apps
Ben Limmer
 
Fun with Ember 2.x Features
Fun with Ember 2.x FeaturesFun with Ember 2.x Features
Fun with Ember 2.x Features
Ben Limmer
 
Building a Single Page Application using Ember.js ... for fun and profit
Building a Single Page Application using Ember.js ... for fun and profitBuilding a Single Page Application using Ember.js ... for fun and profit
Building a Single Page Application using Ember.js ... for fun and profit
Ben Limmer
 
Automated Testing in EmberJS
Automated Testing in EmberJSAutomated Testing in EmberJS
Automated Testing in EmberJS
Ben Limmer
 
Deploying a Location-Aware Ember Application
Deploying a Location-Aware Ember ApplicationDeploying a Location-Aware Ember Application
Deploying a Location-Aware Ember Application
Ben Limmer
 

More from Ben Limmer (9)

Tips & Tricks for Being a Successful Tech Lead
Tips & Tricks for Being a Successful Tech LeadTips & Tricks for Being a Successful Tech Lead
Tips & Tricks for Being a Successful Tech Lead
 
1-Up Your Git Skills
1-Up Your Git Skills1-Up Your Git Skills
1-Up Your Git Skills
 
Maximize your output (sans productivity shame)
Maximize your output (sans productivity shame)Maximize your output (sans productivity shame)
Maximize your output (sans productivity shame)
 
[OLD] Understanding Github PR Merge Options (1up-ing your git skills part 2)
[OLD] Understanding Github PR Merge Options (1up-ing your git skills part 2)[OLD] Understanding Github PR Merge Options (1up-ing your git skills part 2)
[OLD] Understanding Github PR Merge Options (1up-ing your git skills part 2)
 
Upgrading Ember.js Apps
Upgrading Ember.js AppsUpgrading Ember.js Apps
Upgrading Ember.js Apps
 
Fun with Ember 2.x Features
Fun with Ember 2.x FeaturesFun with Ember 2.x Features
Fun with Ember 2.x Features
 
Building a Single Page Application using Ember.js ... for fun and profit
Building a Single Page Application using Ember.js ... for fun and profitBuilding a Single Page Application using Ember.js ... for fun and profit
Building a Single Page Application using Ember.js ... for fun and profit
 
Automated Testing in EmberJS
Automated Testing in EmberJSAutomated Testing in EmberJS
Automated Testing in EmberJS
 
Deploying a Location-Aware Ember Application
Deploying a Location-Aware Ember ApplicationDeploying a Location-Aware Ember Application
Deploying a Location-Aware Ember Application
 

Recently uploaded

Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptxSecstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
nkrafacyberclub
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
Aftab Hussain
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
Neo4j
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
Kari Kakkonen
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
Neo4j
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
Prayukth K V
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
Uni Systems S.M.S.A.
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 

Recently uploaded (20)

Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptxSecstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 

Building Realtime Apps with Ember.js and WebSockets

  • 1. Building Real-Time Apps with EmberJS & WebSockets
  • 2. Ben LimmerGEMConf - 5/21/2016 ember.party blimmer
  • 3. Ben LimmerEmberJS Meetup - 2/24/2016 ember.party ♥
  • 4. Ben LimmerGEMConf - 5/21/2016 ember.party Talk Roadmap • WebSockets vs. AJAX • Fundamentals of WebSockets • Code! • Other Considerations
  • 5. Ben LimmerGEMConf - 5/21/2016 ember.party request response request response AJAX
  • 6. Ben LimmerGEMConf - 5/21/2016 ember.party with a lot of apps, this paradigm still works
  • 7. Ben LimmerGEMConf - 5/21/2016 ember.party but what about real-time apps?
  • 8. Ben LimmerGEMConf - 5/21/2016 ember.party e.g.
  • 9. Ben LimmerGEMConf - 5/21/2016 ember.party live dashboards
  • 10. Ben LimmerGEMConf - 5/21/2016 ember.party Source: http://www.heckyl.com/
  • 11. Ben LimmerGEMConf - 5/21/2016 ember.party 2nd screen apps
  • 12. Ben LimmerGEMConf - 5/21/2016 ember.party© MLB / Source: MLB.com
  • 13. Ben LimmerGEMConf - 5/21/2016 ember.party deployment notifications
  • 14. Ben LimmerGEMConf - 5/21/2016 ember.party Source: inbox.google.com
  • 15. Ben LimmerGEMConf - 5/21/2016 ember.party games
  • 16. Ben LimmerGEMConf - 5/21/2016 ember.party Source: http://browserquest.mozilla.org/img/common/promo-title.jpg
  • 17. Ben LimmerGEMConf - 5/21/2016 ember.party chat gamesdeployment notifications live dashboards 2nd screen apps activity streams comment sections realtime progress collaborative editing
  • 18. Ben LimmerGEMConf - 5/21/2016 ember.party how do we build a real-time app?
  • 19. Ben LimmerGEMConf - 5/21/2016 ember.party update? nope. (old way) short polling update? nope. data update? yep!
  • 20. Ben LimmerGEMConf - 5/21/2016 ember.party (old way) long polling request Keep-Alive timeout request Keep-Alive data response request Keep-Alive
  • 21. Ben LimmerGEMConf - 5/21/2016 ember.party WebSockets handshake connection opened bi-directional communication
  • 22. Ben LimmerGEMConf - 5/21/2016 ember.party WebSockets no polling full duplex over TCP communication over standard HTTP(S) ports broadcast to all connected clients
  • 23. Ben LimmerGEMConf - 5/21/2016 ember.party Talk Roadmap • WebSockets vs. AJAX • Fundamentals of WebSockets • Code! • Other Considerations
  • 24. Ben LimmerGEMConf - 5/21/2016 ember.party the handshake
  • 25. Ben LimmerGEMConf - 5/21/2016 ember.party Request GET wss://example.org/socket HTTP/1.1 Origin: https://example.org Host: example.org Sec-WebSocket-Key: zy6Dy9mSAIM7GJZNf9rI1A== Upgrade: websocket Connection: Upgrade Sec-WebSocket-Version: 13 Response HTTP/1.1 101 Switching Protocols Connection: Upgrade Sec-WebSocket-Accept: EDJa7WCAQQzMCYNJM42Syuo9SqQ= Upgrade: websocket
  • 26. events • open • message • error • close • send • close methods
  • 27. Ben LimmerGEMConf - 5/21/2016 ember.party WebSocket.send()
  • 28. Ben LimmerGEMConf - 5/21/2016 ember.party send(String 'foo'); send(Blob 010101); send(ArrayBuffer file);
  • 29. Ben LimmerGEMConf - 5/21/2016 ember.party WebSocket.send(’YOLO’);
  • 30. Ben LimmerGEMConf - 5/21/2016 ember.party sub-protocols • a contract between client/server • 2 classes of sub-protocols • well-defined (e.g. STOMP, WAMP) • application specific protocols
  • 31. Ben LimmerGEMConf - 5/21/2016 ember.party Request with Protocol GET wss://example.org/socket HTTP/1.1 Origin: https://example.org Host: example.org Sec-WebSocket-Key: zy6Dy9mSAIM7GJZNf9rI1A== Upgrade: websocket Connection: Upgrade Sec-WebSocket-Version: 13 Sec-WebSocket-Protocol: v10.stomp
  • 32. Ben LimmerGEMConf - 5/21/2016 ember.party STOMP SEND destination:/queue/a hello queue a ^@ MESSAGE destination:/queue/a message-id: <message-identifier> hello queue a ^@
  • 33. Ben LimmerGEMConf - 5/21/2016 ember.party STOMP SEND destination:/queue/a hello queue a ^@
  • 34. Ben LimmerGEMConf - 5/21/2016 ember.party subprotocols bring structure to ws
  • 35. Ben LimmerGEMConf - 5/21/2016 ember.party Talk Roadmap • AJAX vs. WebSockets • Fundamentals of WebSockets • Code! • Other Considerations
  • 36. Ben LimmerGEMConf - 5/21/2016 ember.party let’s build something!
  • 37. Ben LimmerGEMConf - 5/21/2016 ember.party
  • 38. Ben LimmerEmberJS Meetup - 2/24/2016 ember.party alice clicks bob / everyone sees
  • 39. Ben LimmerEmberJS Meetup - 2/24/2016 ember.party bob clicks alice / everyone sees
  • 40. Ben LimmerGEMConf - 5/21/2016 ember.party npm install ws
  • 41. Ben LimmerGEMConf - 5/21/2016 ember.party
  • 42. Ben LimmerGEMConf - 5/21/2016 ember.party • fast • simple WebSocket implementation • few bells and whistles npm install ws
  • 43. Ben LimmerGEMConf - 5/21/2016 ember.party server/index.js 1 const WebSocketServer = require('ws').Server; 2 3 const wss = new WebSocketServer({ 4 port: process.env.PORT 5 });
  • 44. Ben LimmerGEMConf - 5/21/2016 ember.party waiting for socket connection…
  • 45. Ben LimmerGEMConf - 5/21/2016 ember.party ember install ember-websockets
  • 46. Ben LimmerGEMConf - 5/21/2016 ember.party
  • 47. Ben LimmerGEMConf - 5/21/2016 ember.party ember install ember-websockets • integrates with the Ember runloop • is an Ember.ObjectProxy • abstracts away the WebSocket
  • 48. Ben LimmerGEMConf - 5/21/2016 ember.party app/services/rt-ember-socket.js 1 websockets: service(), 2 3 init() { 4 this._super(...arguments); 5 6 const socket = this.get('websockets').socketFor(host); 7 8 socket.on('open', this.open, this); 9 socket.on('close', this.reconnect, this); 10 }, 11 12 online: false, 13 open() { 14 this.set('online', true); 15 }, 16 17 reconnect() { 18 this.set('online', false); 19 20 Ember.run.later(this, () => { 21 this.get('socket').reconnect(); 22 }, 5000); 23 },
  • 49. Ben LimmerGEMConf - 5/21/2016 ember.party
  • 50. Ben LimmerGEMConf - 5/21/2016 ember.party rtember-1.0 - sub-protocol
  • 51. Ben LimmerGEMConf - 5/21/2016 ember.party rtember-1.0 - sub-protocol data events
  • 52. Ben LimmerGEMConf - 5/21/2016 ember.party server/index.js 1 const WebSocketServer = require('ws').Server; 2 3 const wss = new WebSocketServer({ 4 port: process.env.PORT, 5 handleProtocols: function(protocol, cb) { 6 const supportedProtocol = 7 protocol[protocol.indexOf('rtember-1.0')]; 8 if (supportedProtocol) { 9 cb(true, supportedProtocol); 10 } else { 11 cb(false); 12 } 13 }, 14 });
  • 53. Ben LimmerGEMConf - 5/21/2016 ember.party
  • 54. Ben LimmerGEMConf - 5/21/2016 ember.party app/services/rt-ember-socket.js 1 websockets: Ember.inject.service(), 2 3 socket: null, 4 init() { 5 this._super(...arguments); 6 7 const socket = this.get('websockets') 8 .socketFor(host, ['rtember-1.0']); 9 10 socket.on('open', this.open, this); 11 socket.on('close', this.reconnect, this); 12 13 this.set('socket', socket); 14 },
  • 55. Ben LimmerGEMConf - 5/21/2016 ember.party
  • 56. Ben LimmerGEMConf - 5/21/2016 ember.party rtember-1.0 - sub-protocol data events
  • 57. Ben LimmerGEMConf - 5/21/2016 ember.party rtember-1.0 - sub-protocol { "frameType": "event", "payload": { “eventType": ... event type ..., "eventInfo": ... event info ... } } { "frameType": "data", "payload": { ... json api payload ... } } or
  • 58. Ben LimmerGEMConf - 5/21/2016 ember.party rtember-1.0 - sub-protocol data events
  • 59. Ben LimmerGEMConf - 5/21/2016 ember.party 1 wss.on('connection', function(ws) { 2 sendInitialGifs(ws); 3 }); 4 5 function sendInitialGifs(ws) { 6 const gifs = gifDb; 7 const random = _.sampleSize(gifs, 25); 8 9 sendDataToClient(ws, serializeGifs(random)); 10 } 11 12 function sendDataToClient(ws, payload) { 13 const payload = { 14 frameType: FRAME_TYPES.DATA, 15 payload, 16 } 17 ws.send(JSON.stringify(payload)); 18 }
  • 60. Ben LimmerGEMConf - 5/21/2016 ember.party app/services/rt-ember-socket.js 1 init() { 2 ... 3 socket.on('message', this.handleMessage, this); 4 ... 5 }, 6 7 handleMessage(msg) { 8 const { frameType, payload } = JSON.parse(msg.data); 9 10 if (frameType === FRAME_TYPES.DATA) { 11 this.handleData(payload); 12 } else { 13 warn(`Encountered unknown frame type: ${frameType}`); 14 } 15 }, 16 17 handleData(payload) { 18 this.get('store').pushPayload(payload); 19 }
  • 61. Ben LimmerGEMConf - 5/21/2016 ember.party
  • 62. Ben LimmerGEMConf - 5/21/2016 ember.party { "frameType": "data", "payload": { "data": [{ "type": "gif", "id": "3o8doPV2heuYjdN2Fy", "attributes": { "url": "http://giphy.com/3o8doPV2heuYjdN2Fy/giphy.gif" } }, { ... }, { ... }] } }
  • 63. Ben LimmerGEMConf - 5/21/2016 ember.party
  • 64. Ben LimmerGEMConf - 5/21/2016 ember.party app/routes/index.js 1 export default Ember.Route.extend({ 2 model() { 3 return this.store.peekAll('gif'); 4 } 5 });
  • 65. Ben LimmerGEMConf - 5/21/2016 ember.party
  • 66. Ben LimmerGEMConf - 5/21/2016 ember.party app/templates/index.hbs {{gif-tv gifs=model}} app/templates/components/gif-tv.hbs <div class='suggestions'> {{#each gifs as |gif|}} <img src={{gif.url}} /> {{/each}} </div>
  • 67. Ben LimmerGEMConf - 5/21/2016 ember.party
  • 68. Ben LimmerGEMConf - 5/21/2016 ember.party
  • 69. Ben LimmerGEMConf - 5/21/2016 ember.party rtember-1.0 - sub-protocol data events
  • 70. Ben LimmerGEMConf - 5/21/2016 ember.party rtember-1.0 - sub-protocol { "frameType": "event", "payload": { “eventType": ... event type ..., "eventInfo": ... event info ... } }
  • 71. Ben LimmerGEMConf - 5/21/2016 ember.party Share GIF Event { "frameType": "event", "payload": { "eventType": "share_gif", "eventInfo": "<gif_id>" } } { "frameType": "data", "payload": {[ <shared_gif>, <previously_shared_gif> ]} }
  • 72. Ben LimmerGEMConf - 5/21/2016 ember.party { "frameType": "data", "payload": { "data": [ { "type": "gifs", "id": "3o8doPV2heuYjdN2Fy", "attributes": { "url": "http://giphy.com/3o8doPV2heuYjdN2Fy/giphy.gif", "shared": false } }, { "type": "gifs", "id": "xTiQyBOIQe5cgiyUPS", "attributes": { "url": "http://giphy.com/xTiQyBOIQe5cgiyUPS/giphy.gif", "shared": true } } ] } }
  • 73. Ben LimmerGEMConf - 5/21/2016 ember.party app/templates/components/gif-tv.hbs <div class='suggestions'> {{#each gifs as |gif|}} <img {{action shareGif gif}} src={{gif.url}} /> {{/each}} </div> app/components/gif-tv.js 1 export default Ember.Component.extend({ 2 rtEmberSocket: service(), 3 4 shareGif(gif) { 5 this.get('rtEmberSocket') 6 .sendEvent(EVENTS.SHARE_GIF, gif.get('id')); 7 }, 8 });
  • 74. Ben LimmerGEMConf - 5/21/2016 ember.party 6 .sendEvent(EVENTS.SHARE_GIF, gif.get('id')); 7 }, 8 }); app/services/rt-ember-socket.js 1 sendEvent(eventType, eventInfo) { 2 this.get('socket').send(JSON.stringify({ 3 frameType: FRAME_TYPES.EVENT, 4 payload: { 5 eventType, 6 eventInfo, 7 }, 8 })); 9 }
  • 75. Ben LimmerEmberJS Meetup - 2/24/2016 ember.party 1 ws.on('message', function(rawData) { 2 const data = JSON.parse(rawData); 3 4 if (data.frameType === FRAME_TYPES.EVENT) { 5 const newShare = _.find(gifDb, { 6 id: data.payload.eventInfo 7 }); 8 const previouslyShared = _.find(gifDb, 'shared'); 9 10 newShare.shared = true; 11 previouslyShared.shared = false; 12 13 const framePayload = { 14 frameType: FRAME_TYPES.DATA, 15 payload: serializeGifs([previouslyShared, newShare]), 16 }; 17 const rawPayload = JSON.stringify(framePayload); 18 wss.clients.forEach((client) => { 19 client.send(rawPayload); 20 }); 21 } 22 });
  • 76. Ben LimmerGEMConf - 5/21/2016 ember.party beware
  • 77. Ben LimmerGEMConf - 5/21/2016 ember.party 1 ws.on('message', function(rawData) { 2 try { 3 const data = JSON.parse(rawData); 4 5 if (data.frameType === FRAME_TYPES.EVENT) { 6 if (data.payload.eventType !== EVENTS.SHARE_GIF) { 7 throw Error(); // unknown event 8 } 9 10 const newShare = ...; 11 if (!newShare) { 12 throw Error(); // unknown gif 13 } 14 ... 15 } 16 } catch(e) { 17 ws.close(1003); // unsupported data 18 } 19 });
  • 78. Ben LimmerGEMConf - 5/21/2016 ember.party { "frameType": "data", "payload": { "data": [ { "type": "gifs", "id": "3o8doPV2heuYjdN2Fy", "attributes": { "url": "http://giphy.com/3o8doPV2heuYjdN2Fy/giphy.gif", "shared": false } }, { "type": "gifs", "id": "xTiQyBOIQe5cgiyUPS", "attributes": { "url": "http://giphy.com/xTiQyBOIQe5cgiyUPS/giphy.gif", "shared": true } } ] } }
  • 79. Ben LimmerGEMConf - 5/21/2016 ember.party app/templates/components/gif-tv.hbs app/components/gif-tv.js 1 export default Ember.Component.extend({ 2 sharedGif: computed('gifs.@each.shared', function() { 3 return this.get('gifs').findBy('shared', true); 4 }), 5 }); <div class='shared-gif'> <img src={{sharedGif.url}} /> </div> <div class='suggestions'> <!-- ... --> </div>
  • 80. Ben LimmerGEMConf - 5/21/2016 ember.party
  • 81. Ben LimmerGEMConf - 5/21/2016 ember.party ember.party/gemconf
  • 82. Ben LimmerGEMConf - 5/21/2016 ember.party
  • 83. Ben LimmerGEMConf - 5/21/2016 ember.party Talk Roadmap • AJAX vs. WebSockets • Fundamentals of WebSockets • Code! • Other Considerations
  • 84. Ben LimmerGEMConf - 5/21/2016 ember.party other considerations • security • websocket support (libraries) • learn from example
  • 85. Ben LimmerGEMConf - 5/21/2016 ember.party security • Use TLS (wss:// vs. ws://) • Verify the Origin header • Verify the request by using a random token on handshake source: WebSocket (Andrew Lombardi) - O’Reilly
  • 86. Ben LimmerGEMConf - 5/21/2016 ember.party other considerations • security • websocket support (libraries) • learn from example
  • 87. Ben LimmerGEMConf - 5/21/2016 ember.party support
  • 88. Ben LimmerGEMConf - 5/21/2016 ember.party 9
  • 89. Ben LimmerGEMConf - 5/21/2016 ember.party socket.io • Graceful fallback to polling / flash (!) • Syntactic Sugar vs. ws package • Support in ember-websockets add-on
  • 90. Ben LimmerGEMConf - 5/21/2016 ember.party
  • 91. Ben LimmerGEMConf - 5/21/2016 ember.party pusher.com • Graceful fallback • Presence support • Authentication / Security strategies • No infrastructure required
  • 92. Ben LimmerGEMConf - 5/21/2016 ember.party other considerations • security • websocket support (libraries) • learn from example
  • 93. Ben LimmerGEMConf - 5/21/2016 ember.party learn by example
  • 94. Ben LimmerGEMConf - 5/21/2016 ember.party learn by example
  • 95. Ben LimmerGEMConf - 5/21/2016 ember.party https://github.com/blimmer/real-time-ember-client https://github.com/blimmer/real-time-ember-server l1m5blimmer
  • 96. Ben LimmerGEMConf - 5/21/2016 ember.party thanks!
  • 97. • WebSocket: Lightweight Client-Server Communications (O’Reilly) • WebSockets: Methods for Real-Time Data Streaming (Steve Schwartz) Credits
  • 98. • pusher.com • socket.io • node ws • websocket security (heroku) Resources