The document discusses client-server communication and introduces several JavaScript libraries for facilitating this communication. It begins by outlining common methods for browsers to communicate (HTTP, WebSockets, WebRTC) and issues with existing approaches. It then introduces the rest.js, msgs.js, and SockJS libraries. Rest.js provides a thin wrapper for making requests that embraces HTTP. Msgs.js implements enterprise integration patterns for messaging. Examples show how these can be used to build scalable broadcast servers and integrate client-server communication.
2. About me
• engineer @ SpringSource / Pivotal
• contributor to cujoJS
• drifter
• application framework
• open source commercial
• client server
• front-end back-end
3. A brief word from my sponsor
• leader in Enterprise Java
• now part of Pivotal
• Spring
• Cloud Foundry
• Redis
• RabbitMQ & SockJS
• Groovy & Grails
• Pivotal Labs
6. We use jQuery, duh
$.get('/usersList.php',
function (response) { ... });
7. We use jQuery, duh
$.get('/usersList.php').then(
function (response) { ... }
);
...not to start a holy war, but I like promises
8. What's wrong here?
$.ajax({
url: '/usersList.php',
data: { page: 1, count: 50 }
}).then(
function (response) { ... },
function (error) { ... }
);
...lot of little nits, but it's not too bad
10. Abstract the common bits
function loadUsers(pageNum) {
return $.ajax({
url: '/usersList.php',
data: { page: pageNum, count: 50 }
});
}
loadUsers(1).then(
function (response) { ... },
function (error) { ... }
);
11. Poor abstractions
• abstracts HTTP rather than embracing it
• it's not just jQuery
• every 'Ajax' lib suffers from this issue
• should abstract interacting with resources rather than
mechanics of making requests
12. rest.js
• very thin wrapper around a raw request/response
• XHR, Node, JSONP, IE XDomainRequest
• AMD and CommonJS/Node
• MIT licensed, part of cujoJS
13. How do I use rest.js?
var rest = require('rest');
-- or --
define(['rest'], function (rest) {
...
});
14. How do I use rest.js?
rest('/usersList.php').then(
function (response) { ... }
);
...wait a minute
16. rest.js
• abstraction to work with resources, rather than just an
abstraction to make requests
• full access to all aspects of the request and response,
including response headers
• advanced behavior applied with interceptors
• configure behavior once, share
17. What makes rest.js different?
• Interceptors!
• apply advanced behavior to the request/response
• encapsulate configuration
• use what you need
18. What's an interceptor?
var client = rest.chain(basicAuthInterceptor, {
username: 'marisa',
password: 'koala'
});
client('/usersList.php').then(
function (response) {
... authenticated response...
}
);
19. What can interceptors do?
• almost anything
• hook into the request/response lifecycle
• augment or replace a request/response
• provide an alternate client
• detect and/or recover from errors
• abort the request
24. Chaining interceptors
• extend a client applying behavior to requests/response
resulting in a new client
• client can be safely shared within an application
• clients are immutable
26. Interceptors in practice
var client = rest.chain(basicAuthInterceptor, {
username: 'marisa',
password: 'koala'
})
.chain(errorCodeInterceptor, { code: 500 })
.chain(mimeInterceptor, { mime: 'application/json' })
.chain(hateoasInterceptor);
...I heard about this OAuth thing, can you use it instead of whatever we currently do?
27. Interceptors in practice
var client = rest.chain(oAuthInterceptor, {
clientId: 'myapp',
scope: 'read,write',
authorizationUrl: 'http://example.com/oauth',
redirectUrl: 'http://myapp.com/oauth'
})
.chain(errorCodeInterceptor, { code: 500 })
.chain(mimeInterceptor, { mime: 'application/json' })
.chain(hateoasInterceptor);
• replaced basic auth with OAuth
• request is authenticated under the hood
• other interceptors, consumers don't care
28. What about events?
• no problem
• let’s use WebSockets
• bidirectional communication
• server → client
• client → server
29. The problem with
WebSocket libraries
• abstracts sending and receiving of messages
• little support for interacting with messages
31. msgs.js
• Enterprise Integration Patterns in action
• provides core messaging patterns
• adapters to other messaging APIs
• supports browsers (AMD) and Node.js
• MIT licensed, part of cujoJS
32. Hello World
var bus = require('msgs').bus();
bus.channel('lowercase');
bus.channel('uppercase');
bus.transform(
function (message) { return message.toUpperCase(); },
{ input: 'lowercase', output: 'uppercase' }
);
bus.outboundAdapter(
function (str) { console.log(str); },
{ input: 'uppercase' }
);
bus.send('lowercase', 'hello world'); // 'HELLO WORLD'
34. var bus = require('msgs').bus(),
webSocketServer = ...;
bus.pubsubChannel('fromClient');
bus.pubsubChannel('toClient');
webSocketServer.on('connection', function (connection) {
bus.nodeStreamGateway(connection, {
output: 'fromClient',
input: 'toClient'
});
});
bus.forward('fromClient', 'toClient');
Broadcast server
35. Scalable broadcast server
var bus = require('msgs').bus(),
redis = require('redis'),
webSocketServer = ...;
bus.pubsubChannel('fromClient');
bus.pubsubChannel('toClient');
webSocketServer.on('connection', function (connection) {
bus.nodeStreamGateway(connection, {
output: 'fromClient',
input: 'toClient'
});
});
bus.redisGateway(redis.createClient, 'circles',
{ output: 'toClient', input: 'fromClient' });
36. Let's not forget about the client
var bus = require('msgs').bus(),
SockJS = require('sockjs');
bus.channel('toServer');
bus.channel('fromServer');
bus.webSocketGateway(
new SockJS('/msgs'),
{ output: 'fromServer', input: 'toServer' }
);
...
Full source: https://github.com/know-cujojs/circles
See it running: http://cujojs-circles.cloudfoundry.com/