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

Asynchronous Web Interfaces

Baf018e2cc4616e4776d323215c7136c?s=47 Alex MacCaw
July 07, 2012
2k

Asynchronous Web Interfaces

Oh how to lie, cheat and steal.

Baf018e2cc4616e4776d323215c7136c?s=128

Alex MacCaw

July 07, 2012
Tweet

Transcript

  1. @maccman July 2012 Asynchronous User Interfaces

  2. None
  3. What makes design?

  4. None
  5. Interaction is fundament to design

  6. What makes interaction

  7. Speed is fundamental to interaction

  8. None
  9. • Amazon: 100 ms of extra load time caused a

    1% drop in sales • Google: 500 ms of extra load time caused 20% fewer searches • Yahoo!: 400 ms of extra load time caused a 5–9% increase in the number of people who clicked “back” before the page even loaded
  10. It’s not speed, it’s perceived speed

  11. Network is always a bottleneck

  12. So why would you tie your interface to your network

    connection?
  13. Because it’s easy.

  14. But it’s not sufficient

  15. None
  16. None
  17. Asynchronous user interfaces are non blocking

  18. Asynchronous UIs do not wait, they lie

  19. Lies are all around us

  20. None
  21. None
  22. None
  23. None
  24. None
  25. None
  26. None
  27. None
  28. None
  29. None
  30. None
  31. None
  32. None
  33. None
  34. Why would you optimize for failure?

  35. Designing an Asyncronous UI

  36. None
  37. $('body').dropArea(); $('body').bind('drop', function(e){ e.preventDefault(); e = e.originalEvent; var files =

    e.dataTransfer.files; for (var i=0; i < files.length; i++) { // Only upload images if (/image/.test(files[i].type)) { createAttachment(files[i]); } }; });
  38. $('body').dropArea(); $('body').bind('drop', function(e){ e.preventDefault(); e = e.originalEvent; var files =

    e.dataTransfer.files; for (var i=0; i < files.length; i++) { // Only upload images if (/image/.test(files[i].type)) { createAttachment(files[i]); } }; });
  39. $('body').dropArea(); $('body').bind('drop', function(e){ e.preventDefault(); e = e.originalEvent; var files =

    e.dataTransfer.files; for (var i=0; i < files.length; i++) { // Only upload images if (/image/.test(files[i].type)) { createAttachment(files[i]); } }; });
  40. Secret sauce is generating client side GUIDs

  41. var createAttachment = function(file) { var uid = [App.username, (new

    Date).getTime(), 'raw'].join('-'); var data = new FormData(); data.append('attachment[file]', file); data.append('attachment[uid]', uid); $.ajax({ url: '/attachments', data: data, cache: false, contentType: false, processData: false, type: 'POST', }) };
  42. var createAttachment = function(file) { var uid = [App.username, (new

    Date).getTime(), 'raw'].join('-'); var data = new FormData(); data.append('attachment[file]', file); data.append('attachment[uid]', uid); $.ajax({ url: '/attachments', data: data, cache: false, contentType: false, processData: false, type: 'POST', }) };
  43. var createAttachment = function(file) { var uid = [App.username, (new

    Date).getTime(), 'raw'].join('-'); var data = new FormData(); data.append('attachment[file]', file); data.append('attachment[uid]', uid); $.ajax({ url: '/attachments', data: data, cache: false, contentType: false, processData: false, type: 'POST', }) };
  44. Instant feedback

  45. var absText = '![' file.name + '](/attachments/' + uid +

    ')'; $('.edit').insertAtCaret(absText);
  46. Parts to an Async UI: • Render on the client

    • Store state & data on the client • Communicate with the server asynchronously
  47. Rendering on the client is easy and fast

  48. Mustache Underscore nano Hogan milk jquery.tmpl EJS dust.js doT.js jaml

    icanhaz jade pure Handlebars.js Eco
  49. app/assets/javascripts/views/users.jst.eco

  50. First name: <%= @firstName %> app/assets/javascripts/views/users.jst.eco

  51. window.JST['views/users']({firstName: 'User Name'})

  52. http://styloapp.com

  53. None
  54. requestAnimationFrame()

  55. Batch up DOM updates

  56. Catapult

  57. $ catapult new myapp create myapp create myapp/assets/javascripts/app.js create myapp/assets/stylesheets/app.css

    create myapp/browser.json create myapp/public/index.htm $ cd myapp
  58. $ catapult server $ catapult build $ catapult watch

  59. //= require jquery //= require_tree ./app

  60. Storing state and data on the client

  61. MVC = Backbone / Spine / Ember

  62. Store state in the controllers

  63. Store data in the models

  64. Preload data

  65. { users: [ { name: "Johnny", assets: [ { name:

    "A file" }, ... ] }, ... ] }
  66. Validate everything on the client

  67. validate: function(){ if ( !this.name ) return 'name required'; if

    ( isNaN(parseInt(this.amount, 10)) ) return 'amount is invalid'; };
  68. Asynchronous server communication

  69. Chat example http://spainjs.herokuapp.com/

  70. None
  71. Chat example http://spainjs.herokuapp.com/ Source https://gist.github.com/3061694

  72. $.post('/', {msg: value}, function(){ addMessage({data: value}); });

  73. $.post('/', {msg: value}); addMessage({data: value});

  74. get '/stream', :provides => 'text/event-stream' do stream :keep_open do |out|

    streams << out out.callback { streams.delete(out) } end end post '/' do msg = params[:msg] streams.each do |out| out << "data: #{msg}\n\n" end 204 end
  75. var es = new EventSource('/stream'); es.onmessage = function(e) { addMessage(e.data);

    };
  76. What Spine & Backbone give you

  77. • CIDs • Async model API • Serial Ajax requests

  78. model.save();

  79. model.save(null, {wait: true});

  80. render: function(){ model.bind('change', function(){ this.$el.html(template(model)) }.bind(this)); }, update: function(){ model.save({

    name: this.$name.val() }); },
  81. While requests are still pending

  82. window.onbeforeunload = function(){ if (jQuery.active) return 'Are you sure you

    want to exit?'; };
  83. When the server fails

  84. Quick recap

  85. 1. Lie 2. Cheat 3. Steal

  86. • Don’t block the interface • Async network requests •

    Store state on the client • Render views on the client • Intelligently preload data
  87. Thank you! @maccman http://blog.alexmaccaw.com