Skip to content

Instantly share code, notes, and snippets.

@ben-bradley
Last active August 29, 2015 14:02
Show Gist options
  • Save ben-bradley/651de8ca850c2ec4506c to your computer and use it in GitHub Desktop.
Save ben-bradley/651de8ca850c2ec4506c to your computer and use it in GitHub Desktop.
Making Express, Socket.IO, and Angular play nicely together
// File: client/scripts/controllers/main.js
// With this, you can use 'socket' very nicely (IMHO)
'use strict';
angular.module('theApp')
.controller('MainCtrl', function ($scope, socket) {
$scope.now = 'loading...';
var ioTime = socket.connect('/io/time');
ioTime.on('time', function(now) {
$scope.now = now;
});
var ioPing = socket.connect('/io/ping');
ioPing.on('pong', function(data) {
console.log(data);
});
});
// File: server/server.js
// This is the Node file to fire up an Socket.IO enabled Express server
// Code your io stuff as normal
var express = require('express'),
session = require('express-session'),
bodyParser = require('body-parser'),
cookieParser = require('cookie-parser'),
http = require('http'),
socketio = require('socket.io');
var app = express();
var server = http.createServer(app);
var io = socketio.listen(server);
var sessionStore = new session.MemoryStore();
app.use(express.static(__dirname+'/../client')); // serve the client
app.use(bodyParser());
app.use(cookieParser());
app.use(session({
store: sessionStore,
secret: ''+new Date().getTime()
}));
// this is the authentication middleware that links the
// Express session with the socket. You need to manage
// the session within the authentication stack of the
// Express app:
/*
app.get('/signout', function(req, res) {
...
req.session.destroy();
...
})
*/
io.use(function(socket, next) {
var cookie = socket.handshake.headers.cookie,
sid = cookie.match(/connect.sid=s%3A([^\.]+)\.*/);
if (sid)
sid = sid[1];
else
return next('no session', false);
sessionStore.get(sid, function(err, session) {
if (!session)
return next('no session', false);
// check every 5 seconds to see if the express session is active
var checkSession = setInterval(function() {
sessionStore.get(sid, function(err, session) {
if (!session) {
socket.disconnect(true);
clearInterval(checkSession);
}
});
}, 5000);
next();
});
});
io.of('/io/ping').on('connection', function(socket) {
setInterval(function() { // emit a pong every 1 sec
socket.emit('pong', { pong: new Date() });
}, 1000);
});
io.of('/io/time').on('connection', function(socket) {
setInterval(function() { // emit a new Date() every .5 sec
socket.emit('time', new Date());
}, 500);
});
server.listen(8000);
// File: client/scripts/services/socket.js
// Here's the good stuff! =)
// Heavily inspired by another developer's work whom I've lost track of
'use strict';
angular.module('theApp')
.service('socket', function($rootScope) {
this.connect = function(namespace) {
console.log('connecting: ', namespace)
var _socket = io.connect(namespace);
_socket._on = _socket.on;
_socket._emit = _socket.emit;
_socket.on = function(eventName, callback) {
_socket._on(eventName, function() {
var args = arguments;
$rootScope.$apply(function() {
callback.apply(_socket, args);
});
});
};
_socket.emit = function(eventName, data, callback) {
_socket._emit(eventName, data, function() {
var args = arguments;
$rootScope.$apply(function() {
if (callback) {
callback.apply(_socket, args);
}
});
});
};
return _socket;
};
})
@ben-bradley
Copy link
Author

This is an example of how I've been able to get Socket.IO and Angular to play nicely with each other. I struggled with getting the $scope to update cleanly and found some example code (but lost the URL for credit, sorry!) that got me pointed in the right direction. I hacked it up to allow for connecting to specific namespaces and this is the result.

My expertise with Angular is limited so it's entirely possible that I've inadvertently created some unintended consequences. If you can identify any, please let me know.

@ben-bradley
Copy link
Author

I'm struggling with authentication on the socket, if anyone has any ideas for nice, clean solutions, please let me know.

@ben-bradley
Copy link
Author

I think I've sorted out the authentication sync between Express & Socket.IO in server.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment