Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RethinkDB+Angular.js: Building realtime web applications

RethinkDB+Angular.js: Building realtime web applications

Jorge Silva

June 16, 2015
Tweet

More Decks by Jorge Silva

Other Decks in Technology

Transcript

  1. What is RethinkDB? • Open source database for building realtime

    web applications • NoSQL database that stores schemaless JSON documents • Distributed database that is easy to scale
  2. Built for Realtime Apps • Subscribe to change notifications from

    database queries • No more polling — the database pushes changes to your app • Reduce the amount of plumbing needed to stream live updates
  3. Sample Document { "name": "Will Riker", "position": "Commander", "height": 193,

    "birthdate": Mon Aug 19 2335, "ships": [ { "name": "USS Pegasus" }, { "name": "USS Potemkin" }, { "name": "USS Enterprise" }, ], ... }
  4. Introduction to ReQL • ReQL embeds natively into your programming

    language • Compose ReQL queries by chaining commands
  5. Additional ReQL Features • Geospatial indexing for location- based queries

    • Date and time functions for time data • Support for storing binary objects • Execute http requests using r.http
  6. Changefeeds • The changes command returns a cursor that receives

    updates • Each update includes the new and old value of the modified record
  7. Changefeeds r.table("users").changes() r.table("users") .insert({name: "Bob"}) Changefeed output: { new_val: {

    id: '362ae837-2e29-4695-adef-4fa415138f90', name: 'Bob', ... }, old_val: null }
  8. Changefeeds r.table("users").changes() r.table("users") .get("362ae837-2e29-4695-adef-4fa415138f90") .update({name: "Bobby"}) Changefeed output: { new_val:

    { id: '362ae837-2e29-4695-adef-4fa415138f90', name: 'Bobby' }, old_val: { id: '362ae837-2e29-4695-adef-4fa415138f90', name: 'Bob' } }
  9. What we need • Add http enpoints for getting and

    adding messages • Create an Angular factory for messages • Setup changefeed in Node.js app • Add realtime listener in factory
  10. What we need • Add http endpoints for getting and

    adding messages • Create an Angular factory for messages • Setup changefeed in Node.js app • Add realtime listener in factory
  11. What we need • Add http endpoints for getting and

    adding messages • Create an Angular factory for messages • Setup changefeed in Node.js app • Add realtime listener in factory
  12. What we need • Add http endpoints for getting and

    adding messages • Create an Angular factory for messages • Setup changefeed in Node.js app • Add realtime listener in factory
  13. HTTP endpoints with Node.js var express = require('express'); var app

    = express(); var server = require('http').Server(app); app .post('/message', function (req, res) { // ... }) .get('/message', function (req, res) { // ... }); server.listen(8000); Create HTTP routes for messages
  14. var express = require('express'); var app = express(); var server

    = require('http').Server(app); app .post('/message', function (req, res) { // ... }) .get('/message', function (req, res) { // ... }); server.listen(8000); Declare POST endpoint HTTP endpoints with Node.js
  15. app .post('/message', function (req, res) { return r.table('messages').insert({ text: req.params.text,

    email: req.params.email, created: (new Date()).getTime() }).run(r.conn); }) .get('/message', function (req, res) { // ... }) Get `messages` table HTTP endpoints with Node.js
  16. app .post('/message', function (req, res) { return r.table('messages').insert({ text: req.params.text,

    email: req.params.email, created: (new Date()).getTime() }).run(r.conn); }) .get('/message', function (req, res) { // ... }) `insert` new document HTTP endpoints with Node.js
  17. app .post('/message', function (req, res) { return r.table('messages').insert({ text: req.params.text,

    email: req.params.email, created: (new Date()).getTime() }).run(r.conn); }) .get('/message', function (req, res) { // ... }) Run the query HTTP endpoints with Node.js
  18. var express = require('express'); var app = express(); var server

    = require('http').Server(app); app .post('/message', function (req, res) { // ... }) .get('/message', function (req, res) { // ... }); server.listen(8000); Declare GET route HTTP endpoints with Node.js
  19. app .post('/message', function (req, res) { // ... }) .get('/message',

    function (req, res) { return r.table('messages') .orderBy({ index: 'created'}) .coerceTo('array') .run(r.conn) .then(function (messages) { res.json(messages); }); }) Get `messages` table HTTP endpoints with Node.js
  20. app .post('/message', function (req, res) { // ... }) .get('/message',

    function (req, res) { return r.table('messages') .orderBy({ index: 'created'}) .coerceTo('array') .run(r.conn) .then(function (messages) { res.json(messages); }); }) Order by time created HTTP endpoints with Node.js
  21. app .post('/message', function (req, res) { // ... }) .get('/message',

    function (req, res) { return r.table('messages') .orderBy({ index: 'created'}) .coerceTo('array') .run(r.conn) .then(function (messages) { res.json(messages); }); }) Run the query HTTP endpoints with Node.js
  22. app .post('/message', function (req, res) { // ... }) .get('/message',

    function (req, res) { return r.table('messages') .orderBy({ index: 'created'}) .coerceTo('array') .run(r.conn) .then(function (messages) { res.json(messages); }); }) Return the results of the query HTTP endpoints with Node.js
  23. What we need • Add http endpoints for getting and

    adding messages • Create an Angular factory for messages • Setup changefeed in Node.js app • Add realtime listener in factory
  24. Message Factory (Client) angular.module('rethinkDBWorkshop.services', []) .factory('MessageFactory', MessageFactory); MessageFactory.$inject = ['$http',

    '$rootScope']; function MessageFactory ($http, $rootScope) { var messageCollection = []; var factory = { insertMessage: insertMessage, getMessageCollection: getMessageCollection, }; factory.getMessageCollection(); return factory; } Creating factory for messages
  25. Message Factory (Client) angular.module('rethinkDBWorkshop.services', []) .factory('MessageFactory', MessageFactory); MessageFactory.$inject = ['$http',

    '$rootScope']; function MessageFactory ($http, $rootScope) { var messageCollection = []; var factory = { insertMessage: insertMessage, getMessageCollection: getMessageCollection, }; factory.getMessageCollection(); return factory; } Declare factory
  26. Message Factory (Client) angular.module('rethinkDBWorkshop.services', []) .factory('MessageFactory', MessageFactory); MessageFactory.$inject = ['$http',

    '$rootScope']; function MessageFactory ($http, $rootScope) { var messageCollection = []; var factory = { insertMessage: insertMessage, getMessageCollection: getMessageCollection, }; factory.getMessageCollection(); return factory; } Inject our dependencies
  27. Message Factory (Client) angular.module('rethinkDBWorkshop.services', []) .factory('MessageFactory', MessageFactory); MessageFactory.$inject = ['$http',

    '$rootScope']; function MessageFactory ($http, $rootScope) { var messageCollection = []; var factory = { insertMessage: insertMessage, getMessageCollection: getMessageCollection, }; factory.getMessageCollection(); return factory; } Declare our messages array
  28. Message Factory (Client) angular.module('rethinkDBWorkshop.services', []) .factory('MessageFactory', MessageFactory); MessageFactory.$inject = ['$http',

    '$rootScope']; function MessageFactory ($http, $rootScope) { var messageCollection = []; var factory = { insertMessage: insertMessage, getMessageCollection: getMessageCollection, }; factory.getMessageCollection(); return factory; } Add method for adding messages
  29. Message Factory (Client) angular.module('rethinkDBWorkshop.services', []) .factory('MessageFactory', MessageFactory); MessageFactory.$inject = ['$http',

    '$rootScope']; function MessageFactory ($http, $rootScope) { var messageCollection = []; var factory = { insertMessage: insertMessage, getMessageCollection: getMessageCollection, }; factory.getMessageCollection(); return factory; } Add method for getting messages
  30. Message Factory (Client) var factory = { insertMessage: function (text)

    { return $http.post('/message', { text: text, email: config.email }); }, getMessageCollection: function () {} }; Send POST http request
  31. Message Factory (Client) var factory = { insertMessage: function (text)

    { return $http.post('/message', { text: text, email: config.email }); }, getMessageCollection: function () {} }; Send object to be inserted
  32. Message Factory (Client) var factory = { insertMessage: function (text)

    { }, getMessageCollection: function () { return $http.get('/message') .then(function (res) { messageCollection.splice(0, Infinity); res.data.forEach(function (row) { messageCollection.push(row); }); return messageCollection; }); } }; GET messages from server
  33. Message Factory (Client) var factory = { insertMessage: function (text)

    { }, getMessageCollection: function () { return $http.get('/message') .then(function (res) { messageCollection.splice(0, Infinity); res.data.forEach(function (row) { messageCollection.push(row); }); return messageCollection; }); } }; Remove all messages from array
  34. Message Factory (Client) var factory = { insertMessage: function (text)

    { }, getMessageCollection: function () { return $http.get('/message') .then(function (res) { messageCollection.splice(0, Infinity); res.data.forEach(function (row) { messageCollection.push(row); }); return messageCollection; }); } }; Add all messages to array
  35. What we need • Add http endpoint for getting and

    adding messages • Create an Angular factory for messages • Setup changefeed in Node.js app • Add realtime listener in factory
  36. Node.js Server var io = require('socket.io')(server); io.on('connection', function (socket) {

    r.connect(config.get('rethinkdb')) .then(function (conn) { r.table('messages') .changes().run(conn) .then(function (cursor) { cursor.each(function (err, row) { socket.emit('message', row.new_val); }); }); }); }); Setup socket handler
  37. Node.js Server var io = require('socket.io')(server); io.on('connection', function (socket) {

    r.connect(config.get('rethinkdb')) .then(function (conn) { r.table('messages') .changes().run(conn) .then(function (cursor) { cursor.each(function (err, row) { socket.emit('message', row.new_val); }); }); }); }); Create Socket.io instance
  38. Node.js Server var io = require('socket.io')(server); io.on('connection', function (socket) {

    r.connect(config.get('rethinkdb')) .then(function (conn) { r.table('messages') .changes().run(conn) .then(function (cursor) { cursor.each(function (err, row) { socket.emit('message', row.new_val); }); }); }); }); Listen for new socket connections
  39. Node.js Server Create a new database connection var io =

    require('socket.io')(server); io.on('connection', function (socket) { r.connect(config.get('rethinkdb')) .then(function (conn) { r.table('messages') .changes().run(conn) .then(function (cursor) { cursor.each(function (err, row) { socket.emit('message', row.new_val); }); }); }); });
  40. Node.js Server var io = require('socket.io')(server); io.on('connection', function (socket) {

    r.connect(config.get('rethinkdb')) .then(function (conn) { r.table('messages') .changes().run(conn) .then(function (cursor) { cursor.each(function (err, row) { socket.emit('message', row.new_val); }); }); }); }); Get `messages` table
  41. Node.js Server var io = require('socket.io')(server); io.on('connection', function (socket) {

    r.connect(config.get('rethinkdb')) .then(function (conn) { r.table('messages') .changes().run(conn) .then(function (cursor) { cursor.each(function (err, row) { socket.emit('message', row.new_val); }); }); }); }); Listen to changes in our messages
  42. Node.js Server var io = require('socket.io')(server); io.on('connection', function (socket) {

    r.connect(config.get('rethinkdb')) .then(function (conn) { r.table('messages') .changes().run(conn) .then(function (cursor) { cursor.each(function (err, row) { socket.emit('message', row.new_val); }); }); }); }); Run the query
  43. Node.js Server var io = require('socket.io')(server); io.on('connection', function (socket) {

    r.connect(config.get('rethinkdb')) .then(function (conn) { r.table('messages') .changes().run(conn) .then(function (cursor) { cursor.each(function (err, row) { socket.emit('message', row.new_val); }); }); }); }); Pass a callback to our cursor
  44. Node.js Server var io = require('socket.io')(server); io.on('connection', function (socket) {

    r.connect(config.get('rethinkdb')) .then(function (conn) { r.table('messages') .changes().run(conn) .then(function (cursor) { cursor.each(function (err, row) { socket.emit('message', row.new_val); }); }); }); }); Send new message to the client
  45. What we need • Add http endpoints for getting and

    adding messages • Create an Angular factory for messages • Setup changefeed in Node.js app • Add realtime listener in factory
  46. Message Factory with Changefeeds function MessageFactory ($http, $rootScope) { var

    socket = io.connect('http://' + config.url); var messageCollection = []; socket.on('message', function (message) { $rootScope.$apply(function () { messageCollection.push(message); }); }); var factory = { ... }; return factory; } Add new message handler
  47. Message Factory with Changefeeds function MessageFactory ($http, $rootScope) { var

    socket = io.connect('http://' + config.url); var messageCollection = []; socket.on('message', function (message) { $rootScope.$apply(function () { messageCollection.push(message); }); }); var factory = { ... }; return factory; } Connection to Socket.io server
  48. Message Factory with Changefeeds function MessageFactory ($http, $rootScope) { var

    socket = io.connect('http://' + config.url); var messageCollection = []; socket.on('message', function (message) { $rootScope.$apply(function () { messageCollection.push(message); }); }); var factory = { ... }; return factory; } Listen to new messages on socket
  49. Message Factory with Changefeeds function MessageFactory ($http, $rootScope) { var

    socket = io.connect('http://' + config.url); var messageCollection = []; socket.on('message', function (message) { $rootScope.$apply(function () { messageCollection.push(message); }); }); var factory = { ... }; return factory; } Perform proper scope life cycle
  50. Message Factory with Changefeeds function MessageFactory ($http, $rootScope) { var

    socket = io.connect('http://' + config.url); var messageCollection = []; socket.on('message', function (message) { $rootScope.$apply(function () { messageCollection.push(message); }); }); var factory = { ... }; return factory; } Push message into collection