Skip to content

Instantly share code, notes, and snippets.

@jaredcnance
Created March 2, 2016 21:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jaredcnance/7211a19e9d116c1c2ce9 to your computer and use it in GitHub Desktop.
Save jaredcnance/7211a19e9d116c1c2ce9 to your computer and use it in GitHub Desktop.
Ember Event Bus
// event-bus.js
// this is an EmberJS service, compatible and tested with Ember 2.3.1
// manages the EventSource for the entire application
import Ember from 'ember';
// TODO: add a method to remove a channel or handler from _openChannels
export default Ember.Service.extend({
store: Ember.inject.service(),
_eventSource: null,
_openChannels: [{
name: 'client.command',
handler: this.clientCommandHandler
}],
_keepAliveTimer: null,
_keepAliveTimeout: 120000,
// channels should be an array of name/handler objects:
// [ ... { name: 'channel-name', handler: function() {...} }, ...]
open(channels) {
let openChannels = this.get('_openChannels');
let reOpenEventSource = false;
Ember.$(channels).each(
(i, channel) => {
// check if the channel is already subscribed to
let [openChannel] = $.grep(openChannels, function(openChannel) {
return openChannel.name === channel.name;
});
if (openChannel) { // channel is already subscribed to
let oldHandler = openChannel.handler;
openChannel.handler = function() {
oldHandler();
channel.handler(); // append the new handler
};
} else { // channel is not subscribed to
reOpenEventSource = true; // need to close and re-open the event source to add the new channel
openChannels.push(channel);
}
}
);
this.set('_openChannels', openChannels);
if (reOpenEventSource) {
this.get('eventSourceReset').call(this);
}
},
eventSourceReset() {
console.log('resetting event source');
let adapter = this.get('store').adapterFor('application');
let source = this.get('_eventSource');
let openChannels = this.get('_openChannels');
if (source) {
source.close();
}
let channelNames = $.map(openChannels,
(channel) => {
return channel.name;
}
).join(',');
let streamUrl = `${adapter.buildURL('live-stream')}?channels=${channelNames}`;
this.get('startKeepAliveTimer').call(this);
source = new EventSource(streamUrl);
this.set('_eventSource', source);
source.addEventListener('message', (event) => {
this.channelMessageHandler.call(this, event);
});
},
channelMessageHandler(event) {
// reset the keep alive timer
this.get('cancelKeepAliveTimer').call(this);
this.get('startKeepAliveTimer').call(this);
// get the channel the message is coming in on and call the handler
let openChannels = this.get('_openChannels');
let payload = JSON.parse(event.data);
let [channel] = $.grep(openChannels, function(channel) {
return channel.name === payload.channel;
});
channel.handler(payload.channel, payload.message);
},
startKeepAliveTimer() {
console.log('keep alive started');
let _keepAliveTimeout = this.get('_keepAliveTimeout');
let _keepAliveTimer = Ember.run.later(this, function() {
this.get('keepAliveHandler').call(this);
}, _keepAliveTimeout);
this.set('_keepAliveTimer', _keepAliveTimer);
},
cancelKeepAliveTimer() {
console.log('keep alive cancelled');
Ember.run.cancel(this.get('_keepAliveTimer'));
},
keepAliveHandler() {
// kill the event source and open a new one
console.log('keep alive fired');
let _eventSource = this.get('_eventSource');
_eventSource.close();
this.get('eventSourceReset').call(this);
},
clientCommandHandler(channel, message) {
switch (message) {
case 'reload':
window.location.reload(true);
break;
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment