Slide 1

Slide 1 text

chat.derbyjs.com/pivotal Tuesday, April 3, 12

Slide 2

Slide 2 text

Tuesday, April 3, 12

Slide 3

Slide 3 text

Keeping Your Clients ‘NSync Node.js and Derby: The New Kids on the Block Lee Edwards April 3, 2012 Tuesday, April 3, 12

Slide 4

Slide 4 text

1995 Tuesday, April 3, 12

Slide 5

Slide 5 text

1996 • Warcraft II • Diablo • Ultima Online Tuesday, April 3, 12

Slide 6

Slide 6 text

Tuesday, April 3, 12

Slide 7

Slide 7 text

Sockets in Python import socket s = socket.socket() s.connect((address, port)) s.send("Request Data") print s.recv(4096) s.close() Tuesday, April 3, 12

Slide 8

Slide 8 text

Complications Tuesday, April 3, 12

Slide 9

Slide 9 text

Enter the Web Browser Tuesday, April 3, 12

Slide 10

Slide 10 text

HTTP Sucks at Games Tuesday, April 3, 12

Slide 11

Slide 11 text

Polling Tuesday, April 3, 12

Slide 12

Slide 12 text

Polling on Rails
Unknown
<%= periodically_call_remote :url => { :action => 'get_inbox_status', :user_id => @user.id}, :update => 'inbox_status', :frequency => 60, :condition => "$('inbox_status').innerHTML == 'Unknown'", :before => "Element.show('progress_indicator')", :complete => "Element.hide('progress_indicator')" }%> Tuesday, April 3, 12

Slide 13

Slide 13 text

Comet Subvert HTTP 1.1 using: • Forever iframe • XHR/multipart • XHR Long Polling Tuesday, April 3, 12

Slide 14

Slide 14 text

Alternatives Tuesday, April 3, 12

Slide 15

Slide 15 text

Promises, Promises Tuesday, April 3, 12

Slide 16

Slide 16 text

One Good Answer • Leave the HTTP 1.1 standard alone • Leave the browser idiosyncrasies alone • Build high-level abstraction on top of them • Client API (Javascript) • Server API (Ruby, or something less cool) Tuesday, April 3, 12

Slide 17

Slide 17 text

Wait, Two Languages? Tuesday, April 3, 12

Slide 18

Slide 18 text

• Server-side Javascript • Built on V8 Engine • Event-driven • Non-blocking I/O Tuesday, April 3, 12

Slide 19

Slide 19 text

• Demo Tuesday, April 3, 12

Slide 20

Slide 20 text

• Node-based MVC framework • Heavily Rails inspired • Includes a router! • Supports sessions! • Has a few templating engine choices! Tuesday, April 3, 12

Slide 21

Slide 21 text

• Hey, look at this code Tuesday, April 3, 12

Slide 22

Slide 22 text

• Compatible with every browser (IE > 5.5) • ...Including mobile browsers! • Cross-domain connections • Heartbeats, timeouts, disconnect events Tuesday, April 3, 12

Slide 23

Slide 23 text

Tuesday, April 3, 12

Slide 24

Slide 24 text

Tuesday, April 3, 12

Slide 25

Slide 25 text

Derby • HTML templating with view bindings • Model syncing • Conflict resolution • Persistence • Performance oriented • Built on Racer - no glue code Tuesday, April 3, 12

Slide 26

Slide 26 text

Demo http://github.com/ledwards/skyhopper Tuesday, April 3, 12

Slide 27

Slide 27 text

File Structure Tuesday, April 3, 12

Slide 28

Slide 28 text

Creating Players get('/play/:gameId?', function(page, model, params) { var gameId = params.gameId; model.subscribe({ _game: 'game.' + params.gameId }, function() { var nextPlayerCount = (model.get('_game.players.length') || 0) + 1; model.push('_game.players', { name: "Player " + nextPlayerCount }); model.set('_game.playerCount', nextPlayerCount); model.ref('_player', '_game.players.' + (nextPlayerCount - 1)); page.render({ gameId: gameId, }); }); }); Tuesday, April 3, 12

Slide 29

Slide 29 text

Creating Cards model.push('_player.cards', { "thumbnail-url": "http://.." + randomInt + ".gif", domId: model.get('_player.name') + model.get('_player.nextCardIndex'), ownerIndex: model.get('_game.players').indexOf(model.get('_player')), cardIndex: model.get('_player.nextCardIndex'), position: { top: "0px", left: "0px" } }); Tuesday, April 3, 12

Slide 30

Slide 30 text

Views Skyhopper: Game #{{_game.id}} </ script> <script src="/javascripts/skyhopper.js"> ... Tuesday, April 3, 12

Slide 31

Slide 31 text

Welcome ((_player.name))

Your name:

There are ((_game.playerCount)) players in the game:

    ((#_game.players))
  • ((.name))
  • ((/))
((#_game.players)) ((.cards > card)) ((/))
... Tuesday, April 3, 12

Slide 32

Slide 32 text

Partials
Tuesday, April 3, 12

Slide 33

Slide 33 text

Events exports.dragEnd = function(e) { var element = $(e.target); var top = element.position().top + "px"; var left = element.position().left + "px"; var card = model.at(element); for (playerIndex in model.get('_game.players')) { card.set('position', { top: top, left: left }); }; } Tuesday, April 3, 12

Slide 34

Slide 34 text

Callbacks model.on('set', '_game.players.*.cards.*.position', function(playerIndex, cardIndex, position) { var domId = model.get('_game.players.' + playerIndex + '.cards.' + cardIndex + '.domId'); var element = jQuery("#" + domId); element.css('left', position.left); element.css('top', position.top); } ); Tuesday, April 3, 12

Slide 35

Slide 35 text

Derbyjs.com Tuesday, April 3, 12