Skip to content

Instantly share code, notes, and snippets.

@ticking-clock
Last active July 25, 2016 21:44
Show Gist options
  • Save ticking-clock/9996381 to your computer and use it in GitHub Desktop.
Save ticking-clock/9996381 to your computer and use it in GitHub Desktop.
Ember.js classes for client-server web socket communication
'use strict'
@App = Ember.Application.create
LOG_TRANSITIONS: true
ready: ->
console.log "app ready, starting server"
@set 'server', App.EventedServer.create
url: '192.168.1.101:8888/game'
delegateType: App.FixtureWebSocket
App.IndexRoute = Ember.Route.extend App.ServerListener,
#model: -> App.GameInfo.findAll() # implementation-dependent list of things
actions:
newGame: -> App.get('server').send App.Actions.StartGame.create()
serverEvents:
# listens for the web socket server to send a 'gameJoin' event
gameJoin: (data) ->
# this is the extent of the gist example; it will fail during this transition attempt
@transitionTo 'game', { id: data.game_id }
App.Action = Ember.Object.extend
data: -> action: 'null_action'
toString: -> JSON.stringify @data()
App.Actions =
StartGame: App.Action.extend
data: ->
action: 'start_game'
FIXTURE: ->
event: 'gameJoin'
game_id: '<new_game_id>'
'use strict'
App.WebSocketDelegate = Ember.Object.extend Ember.Evented,
status:
connecting: 0
open: 1
closed: 2
url: null
ws: null
init: ->
try
ws = new WebSocket "ws://#{@get 'url'}"
ws.onopen = => @trigger 'ready' if ws.readyState is @status.open
ws.onclose = => @trigger 'close'
ws.onmessage = (msg) =>
console.log "Server received: #{msg.data}"
event = msg.data.event # implementation-specific
# trigger the appropriate event for whatever object is listening via the ServerListener mixin
@trigger 'message', event, msg
@set 'ws', ws
catch err
console.error 'Server error: #{err}'
send: (request) ->
json = JSON.stringify request
@get('ws').send json
App.FixtureWebSocketDelegate = Ember.Object.extend Ember.Evented,
fakeDelay: 500
init: ->
setTimeout(=>
@trigger 'ready'
, @fakeDelay)
send: (request) ->
setTimeout(=>
@trigger 'message',
uuid: request.uuid
data: request.action.FIXTURE() # strongly tied to the action object implementation
, @fakeDelay)
'use strict'
App.EventedServer = Ember.Object.extend Ember.Evented,
url: 'http://example.api.com/api'
isReady: false
delegateType: App.WebSocketDelegate
delegate: undefined
requests: undefined
generateUuid: ->
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace /[xy]/g, (c) ->
r = Math.random() * 16 | 0
v = if c is 'x' then r else (r & 0x3 | 0x8)
v.toString 16
init: ->
@_super()
@set 'requests', {}
del = @get('delegateType').create
url: @get 'url'
del.on 'ready', =>
console.log "Server.ready"
@isReady = true
del.on 'close', =>
console.log "Server.closed"
del.on 'message', (msg) =>
request = @get('requests')[msg.uuid]
# TODO: gracefully handle unsolicited messages sent by the server
if not request? then throw Error "Server.message received unknown uuid '#{msg.uuid}"
event = Ember.String.camelize msg.data.event
delete msg.data.event # clear it to not pollute the obj
console.log "Server.message:\t#{event}\t#{JSON.stringify msg.data}"
request.callback.call @, msg.data
@trigger 'message', event, msg.data
# cleanup
delete @get('requests')[msg.uuid]
@set 'delegate', del
send: (action) ->
new Ember.RSVP.Promise (resolve, reject) =>
console.log "Server.send:\t#{action}"
request =
uuid: @generateUuid()
action: action
callback: (data) => resolve(data)
@get('requests')[request.uuid] = request
@get('delegate').send request
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.js"></script>
<script src="http://builds.emberjs.com.s3.amazonaws.com/tags/v1.0.0/ember.js"></script>
<meta charset="utf-8">
<title>Ember.js Web Socket Server Gist</title>
</head>
<body>
<script type="text/x-handlebars">
<button {{action 'newGame'}}>New Game</button>
</script>
</body>
</html>
'use strict'
App.ServerListener = Ember.Mixin.create
serverBinding: Ember.Binding.oneWay 'App.server'
serverObserver: ( ->
@get('server').on 'message', (event, data) =>
@serverEvents[event].call this, data if @serverEvents and @serverEvents[event]
).observes('server').on('init')
Copy link

ghost commented Apr 5, 2014

drunken-octo-wight

Copy link

ghost commented Apr 5, 2014

drunken-octo-wight

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