SlideShare une entreprise Scribd logo
1  sur  44
Télécharger pour lire hors ligne
Sane Async Patterns
       Trevor Burnham
     HTML5DevConf 2013
http://dev.hubspot.com/jobs
https://pragprog.com/books/tbcoffee
https://pragprog.com/books/tbajs
https://leanpub.com/npm
In This Talk

• Callback arguments considered harmful
• Three alternative patterns:
  • PubSub
  • Promises
  • AMD
The Callback Argument
     Anti-Pattern
Pyramid of Doom
mainWindow.menu("File", function(err, file) {
  if(err) throw err;
  file.openMenu(function(err, menu) {
    if(err) throw err;
    menu.item("Open", function(err, item) {
      if(err) throw err;
      item.click(function(err) {
        if(err) throw err;
        window.createDialog('DOOM!', function(err, dialog) {
          if(err) throw err;
          ...
        });
      });
    });
  });
});
A JS-er’s Lament

// Synchronous version of previous slide
try {
  var file = mainWindow.menu("File");
  var menu = file.openMenu();
  var item = menu.item("Open");
  item.click()
  window.createDialog('DOOM!');
} catch (err) {
  ...
}
A Silver Lining

myFunction1();
// No state changes here!
myFunction2();




// Which means we never have to do this...
while (!document.ready) {
  Thread.sleep(0);
}
Mo’ Threads...
Nested Spaghetti
mainWindow.menu("File", function(err, file) {
  if(err) throw err;
  file.openMenu(function(err, menu) {
    if(err) throw err;
    menu.item("Open", function(err, item) {
      if(err) throw err;
      item.click(function(err) {
        if(err) throw err;
        window.createDialog('DOOM!', function(err, dialog) {
          if(err) throw err;
          ...
        });
      });
    });
  });
});
Inflexible APIs
function launchRocketAt(target, callback) {
  var rocket = {x: 0, y: 0},
      step = 0;

    function moveRocket() {
      rocket.x += target.x * (step / 10);
      rocket.y += target.y * (step / 10);
      drawSprite(rocket);
      if (step === 10) {
        callback();
      } else {
        step += 1;
        setTimeout(moveRocket, 50);
      }
    }

    moveRocket();
}
Inflexible APIs


launchRocketAt(target, function() {
  // OK, so the rocket reached its target...
});
Pattern I: PubSub
What is PubSub?

button.on("click", function(event) {
  ...
});


server.on("request", function(req, res, next) {
  ...
});


model.on("change", function() {
  ...
});
What is PubSub for?


• Just about everything!
• When in doubt, use PubSub
How to use it?

• Pick a PubSub library, such as
  https://github.com/Wolfy87/EventEmitter
• If you’re on Node, you already have one
• Simply make your objects inherit from
  EventEmitter, and trigger events on them
An Evented Rocket
Rocket.prototype.launchAt = function(target) {
  rocket = this;
  _.extend(rocket, {x: 0, y: 0, step: 0});

    function moveRocket() {
      // Physics calculations go here...
      if (rocket.step === 10) {
        rocket.emit('complete', rocket);
      } else {
        rock.step += 1;
        setTimeout(moveRocket, 50);
      }
      rocket.emit('moved', rocket);
    }

    rocket.emit('launched', rocket);
    moveRocket();
    return this;
}
An Evented Rocket


var rocket = new Rocket();
rocket.launchAt(target).on('complete', function() {
  // Now it’s obvious what this callback is!
});
PubSub Drawbacks

• No standard
 • Consider using LucidJS:
   https://github.com/RobertWHurst/
   LucidJS
Pattern II: Promises
What is a Promise?

• “A promise represents the eventual value
  returned from the single completion of an
  operation.”
  —The Promises/A Spec
What is a Promise?
• An object that emits an event when an
  async task completes (or fails)


                      Resolved



           Pending



                      Rejected
Example 1: Ajax

var fetchingData = $.get('myData');
fetchingData.done(onSuccess);
fetchingData.fail(onFailure);
fetchingData.state(); // 'pending'

// Additional listeners can be added at any time
fetchingData.done(celebrate);

// `then` is syntactic sugar for done + fail
fetchingData.then(huzzah, alas);
Example 2: Effects

$('#header').fadeTo('fast', 0.5).slideUp('fast');
$('#content').fadeIn('slow');
var animating = $('#header, #content').promise();

animating.done(function() {
  // All of the animations started when promise()
  // was called are now complete.
});
What is a Promise?
• “A promise is a container for an as-yet-
  unknown value, and then’s job is to
  extract the value out of the promise”

  http://blog.jcoglan.com/2013/03/30/
  callbacks-are-imperative-promises-are-
  functional-nodes-biggest-missed-
  opportunity/
Making Promises

// A Promise is a read-only copy of a Deferred
var deferred = $.Deferred();
asyncRead(function(err, data) {
  if (err) {
     deferred.reject();
  } else {
     deferred.resolve(data);
  };
});
var Promise = deferred.promise();
Without Promises
$.fn.loadAndShowContent(function(options) {
  var $el = this;
  function successHandler(content) {
    $el.html(content);
    options.success(content);
  }
  function errorHandler(err) {
    $el.html('Error');
    options.failure(err);
  }
  $.ajax(options.url, {
    success: successHandler,
    error: errorHandler
  });
});
With Promises
$.fn.loadAndShowContent(function(options) {
  var $el = this,
      fetchingContent = $.ajax(options.url);

  fetchingContent.done(function(content) {
    $el.html(content);
  });

  fetchingContent.fail(function(content) {
    $el.html('Error');
  });

  return fetchingContent;
});
Merging Promises

var fetchingData = $.get('myData');
var fadingButton = $button.fadeOut().promise();

$.when(fetchingData, fadingButton)
 .then(function() {
  // Both Promises have resolved
});
Piping Promises

var fetchingPassword = $.get('/password');
fetchingPassword.done(function(password) {
  var loggingIn = $.post('/login', password);
});

// I wish I could attach listeners to the loggingIn
// Promise here... but it doesn’t exist yet!
Piping Promises
var fetchingPassword = $.get('/password');
var loggingIn = fetchingPassword.pipe(function(password) {
  return $.post('/login', password);
});

loggingIn.then(function() {
  // We’ve logged in successfully
}, function(err) {
  // Either the login failed, or the password fetch failed
});

// NOTE: As of jQuery 1.8, then and pipe are synonymous.
// Use `then` for piping if possible.
Piping Promises
var menuFilePromise = mainWindow.menu('file');
var openFilePromise = menuFilePromise.pipe(function(file) {
  return file.openMenu();
});
var menuOpenPromise = openFilePromise.pipe(function(menu) {
  return menu.item('open');
});
var itemClickPromise = menuOpenPromise.pipe(function(item) {
  return item.click()
});
var createDialogPromise = itemClickPromise.pipe(function() {
  return window.createDialog("Promises rock!");
});
A Promise-y Rocket
function launchRocketAt(target) {
  var rocketDeferred = $.Deferred();
  _.extend(rocketDeferred, {x: 0, y: 0, step: 0});

    function moveRocket() {
      // Physics calculations go here...
      rocketDeferred.notify(step / 10);
      if (rocketDeferred.step === 10) {
        rocketDeferred.resolve();
      } else {
        rocketDeferred.step += 1;
        setTimeout(moveRocket, 50);
      }
    }

    moveRocket();
    return rocketDeferred;
}
Promise Drawbacks

• No standard
 • jQuery, Promises/A, Promises/B...
• For maximum benefit, you’ll need
  wrappers all over the place
Pattern III: AMD
What is AMD?

• Asynchronous Module Definition, a spec
• Each module says which modules it needs
• The module’s “factory” is called after all of
  those modules are loaded
What is AMD for?

• Loading dependencies as needed
• Dependency injection (for tests)
• Gating features
How to use AMD

define('myModule', ['jQuery', 'Backbone'],
function($, Backbone) {
  var myModule = {
    // Define some things...
  };

  // If anyone requires this module, they get this object
  return myModule;
});
AMD Drawbacks

• No standard
• Lots of up-front work
• No semantic versioning
• Heavyweight tools (RequireJS)
Alternatives to AMD

• Browserify
 • Simple syntax:   require('./filename');

 • Great if you’re into Node + npm
 • Intended for bundling, not so much for
   async module loading
Conclusion


• The next time you’re about to define a
  function with a callback argument... don’t.
Thanks. Questions?
     @trevorburnham

Contenu connexe

Tendances

Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Paulo Ragonha
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
Igor Bronovskyy
 
AngularJS for designers and developers
AngularJS for designers and developersAngularJS for designers and developers
AngularJS for designers and developers
Kai Koenig
 

Tendances (20)

Workshop 27: Isomorphic web apps with ReactJS
Workshop 27: Isomorphic web apps with ReactJSWorkshop 27: Isomorphic web apps with ReactJS
Workshop 27: Isomorphic web apps with ReactJS
 
AngularJS Internal
AngularJS InternalAngularJS Internal
AngularJS Internal
 
Angular js routing options
Angular js routing optionsAngular js routing options
Angular js routing options
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
Workshop 14: AngularJS Parte III
Workshop 14: AngularJS Parte IIIWorkshop 14: AngularJS Parte III
Workshop 14: AngularJS Parte III
 
Building scalable applications with angular js
Building scalable applications with angular jsBuilding scalable applications with angular js
Building scalable applications with angular js
 
Intro to Ember.JS 2016
Intro to Ember.JS 2016Intro to Ember.JS 2016
Intro to Ember.JS 2016
 
Intro to Ember.js
Intro to Ember.jsIntro to Ember.js
Intro to Ember.js
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
 
[FEConf Korea 2017]Angular 컴포넌트 대화법
[FEConf Korea 2017]Angular 컴포넌트 대화법[FEConf Korea 2017]Angular 컴포넌트 대화법
[FEConf Korea 2017]Angular 컴포넌트 대화법
 
How to Build SPA with Vue Router 2.0
How to Build SPA with Vue Router 2.0How to Build SPA with Vue Router 2.0
How to Build SPA with Vue Router 2.0
 
Angular JS blog tutorial
Angular JS blog tutorialAngular JS blog tutorial
Angular JS blog tutorial
 
Building a js widget
Building a js widgetBuilding a js widget
Building a js widget
 
Enjoy the vue.js
Enjoy the vue.jsEnjoy the vue.js
Enjoy the vue.js
 
Viking academy backbone.js
Viking academy  backbone.jsViking academy  backbone.js
Viking academy backbone.js
 
An introduction to Ember.js
An introduction to Ember.jsAn introduction to Ember.js
An introduction to Ember.js
 
AngularJS for designers and developers
AngularJS for designers and developersAngularJS for designers and developers
AngularJS for designers and developers
 
AngularJs
AngularJsAngularJs
AngularJs
 
Workshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte IIWorkshop 13: AngularJS Parte II
Workshop 13: AngularJS Parte II
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ Etsy
 

En vedette

En vedette (6)

Extending Boomerang
Extending BoomerangExtending Boomerang
Extending Boomerang
 
Кратчайшая история JavaScript
Кратчайшая история JavaScriptКратчайшая история JavaScript
Кратчайшая история JavaScript
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
Web advanced-11-d3 js
Web advanced-11-d3 jsWeb advanced-11-d3 js
Web advanced-11-d3 js
 
Web advanced-01-asincrono
Web advanced-01-asincronoWeb advanced-01-asincrono
Web advanced-01-asincrono
 
Designers from Hell / Freelance Day 2015
Designers from Hell / Freelance Day 2015Designers from Hell / Freelance Day 2015
Designers from Hell / Freelance Day 2015
 

Similaire à Sane Async Patterns

JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
David Padbury
 
Matthew Eernisse, NodeJs, .toster {webdev}
Matthew Eernisse, NodeJs, .toster {webdev}Matthew Eernisse, NodeJs, .toster {webdev}
Matthew Eernisse, NodeJs, .toster {webdev}
.toster
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5a
rajivmordani
 
Javascript Frameworks for Joomla
Javascript Frameworks for JoomlaJavascript Frameworks for Joomla
Javascript Frameworks for Joomla
Luke Summerfield
 

Similaire à Sane Async Patterns (20)

JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
The Promised Land (in Angular)
The Promised Land (in Angular)The Promised Land (in Angular)
The Promised Land (in Angular)
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
Loadrunner
LoadrunnerLoadrunner
Loadrunner
 
Javascript essential-pattern
Javascript essential-patternJavascript essential-pattern
Javascript essential-pattern
 
The Beauty of Java Script
The Beauty of Java ScriptThe Beauty of Java Script
The Beauty of Java Script
 
Matthew Eernisse, NodeJs, .toster {webdev}
Matthew Eernisse, NodeJs, .toster {webdev}Matthew Eernisse, NodeJs, .toster {webdev}
Matthew Eernisse, NodeJs, .toster {webdev}
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5a
 
Javascript Frameworks for Joomla
Javascript Frameworks for JoomlaJavascript Frameworks for Joomla
Javascript Frameworks for Joomla
 
Douglas Crockford: Serversideness
Douglas Crockford: ServersidenessDouglas Crockford: Serversideness
Douglas Crockford: Serversideness
 
Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScript
 
NodeJS
NodeJSNodeJS
NodeJS
 
Java script for web developer
Java script for web developerJava script for web developer
Java script for web developer
 
The evolution of java script asynchronous calls
The evolution of java script asynchronous callsThe evolution of java script asynchronous calls
The evolution of java script asynchronous calls
 
Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practices
 
Async js - Nemetschek Presentaion @ HackBulgaria
Async js - Nemetschek Presentaion @ HackBulgariaAsync js - Nemetschek Presentaion @ HackBulgaria
Async js - Nemetschek Presentaion @ HackBulgaria
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
 
Javascript Memory leaks and Performance & Angular
Javascript Memory leaks and Performance & AngularJavascript Memory leaks and Performance & Angular
Javascript Memory leaks and Performance & Angular
 
You promise?
You promise?You promise?
You promise?
 

Dernier

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Dernier (20)

Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 

Sane Async Patterns

  • 1. Sane Async Patterns Trevor Burnham HTML5DevConf 2013
  • 6. In This Talk • Callback arguments considered harmful • Three alternative patterns: • PubSub • Promises • AMD
  • 7. The Callback Argument Anti-Pattern
  • 8. Pyramid of Doom mainWindow.menu("File", function(err, file) {   if(err) throw err;   file.openMenu(function(err, menu) {     if(err) throw err;     menu.item("Open", function(err, item) {       if(err) throw err;       item.click(function(err) {         if(err) throw err;         window.createDialog('DOOM!', function(err, dialog) {           if(err) throw err;           ...         });       });     });   }); });
  • 9. A JS-er’s Lament // Synchronous version of previous slide try { var file = mainWindow.menu("File");   var menu = file.openMenu();   var item = menu.item("Open");   item.click()   window.createDialog('DOOM!'); } catch (err) { ... }
  • 10. A Silver Lining myFunction1(); // No state changes here! myFunction2(); // Which means we never have to do this... while (!document.ready) { Thread.sleep(0); }
  • 12. Nested Spaghetti mainWindow.menu("File", function(err, file) {   if(err) throw err;   file.openMenu(function(err, menu) {     if(err) throw err;     menu.item("Open", function(err, item) {       if(err) throw err;       item.click(function(err) {         if(err) throw err;         window.createDialog('DOOM!', function(err, dialog) {           if(err) throw err;           ...         });       });     });   }); });
  • 13. Inflexible APIs function launchRocketAt(target, callback) { var rocket = {x: 0, y: 0}, step = 0; function moveRocket() { rocket.x += target.x * (step / 10); rocket.y += target.y * (step / 10); drawSprite(rocket); if (step === 10) { callback(); } else { step += 1; setTimeout(moveRocket, 50); } } moveRocket(); }
  • 14. Inflexible APIs launchRocketAt(target, function() { // OK, so the rocket reached its target... });
  • 16. What is PubSub? button.on("click", function(event) { ... }); server.on("request", function(req, res, next) { ... }); model.on("change", function() { ... });
  • 17. What is PubSub for? • Just about everything! • When in doubt, use PubSub
  • 18. How to use it? • Pick a PubSub library, such as https://github.com/Wolfy87/EventEmitter • If you’re on Node, you already have one • Simply make your objects inherit from EventEmitter, and trigger events on them
  • 19. An Evented Rocket Rocket.prototype.launchAt = function(target) { rocket = this; _.extend(rocket, {x: 0, y: 0, step: 0}); function moveRocket() { // Physics calculations go here... if (rocket.step === 10) { rocket.emit('complete', rocket); } else { rock.step += 1; setTimeout(moveRocket, 50); } rocket.emit('moved', rocket); } rocket.emit('launched', rocket); moveRocket(); return this; }
  • 20. An Evented Rocket var rocket = new Rocket(); rocket.launchAt(target).on('complete', function() { // Now it’s obvious what this callback is! });
  • 21. PubSub Drawbacks • No standard • Consider using LucidJS: https://github.com/RobertWHurst/ LucidJS
  • 23. What is a Promise? • “A promise represents the eventual value returned from the single completion of an operation.” —The Promises/A Spec
  • 24. What is a Promise? • An object that emits an event when an async task completes (or fails) Resolved Pending Rejected
  • 25. Example 1: Ajax var fetchingData = $.get('myData'); fetchingData.done(onSuccess); fetchingData.fail(onFailure); fetchingData.state(); // 'pending' // Additional listeners can be added at any time fetchingData.done(celebrate); // `then` is syntactic sugar for done + fail fetchingData.then(huzzah, alas);
  • 26. Example 2: Effects $('#header').fadeTo('fast', 0.5).slideUp('fast'); $('#content').fadeIn('slow'); var animating = $('#header, #content').promise(); animating.done(function() { // All of the animations started when promise() // was called are now complete. });
  • 27. What is a Promise? • “A promise is a container for an as-yet- unknown value, and then’s job is to extract the value out of the promise” http://blog.jcoglan.com/2013/03/30/ callbacks-are-imperative-promises-are- functional-nodes-biggest-missed- opportunity/
  • 28. Making Promises // A Promise is a read-only copy of a Deferred var deferred = $.Deferred(); asyncRead(function(err, data) { if (err) { deferred.reject(); } else { deferred.resolve(data); }; }); var Promise = deferred.promise();
  • 29. Without Promises $.fn.loadAndShowContent(function(options) { var $el = this; function successHandler(content) { $el.html(content); options.success(content); } function errorHandler(err) { $el.html('Error'); options.failure(err); } $.ajax(options.url, { success: successHandler, error: errorHandler }); });
  • 30. With Promises $.fn.loadAndShowContent(function(options) { var $el = this, fetchingContent = $.ajax(options.url); fetchingContent.done(function(content) { $el.html(content); }); fetchingContent.fail(function(content) { $el.html('Error'); }); return fetchingContent; });
  • 31. Merging Promises var fetchingData = $.get('myData'); var fadingButton = $button.fadeOut().promise(); $.when(fetchingData, fadingButton) .then(function() { // Both Promises have resolved });
  • 32. Piping Promises var fetchingPassword = $.get('/password'); fetchingPassword.done(function(password) { var loggingIn = $.post('/login', password); }); // I wish I could attach listeners to the loggingIn // Promise here... but it doesn’t exist yet!
  • 33. Piping Promises var fetchingPassword = $.get('/password'); var loggingIn = fetchingPassword.pipe(function(password) { return $.post('/login', password); }); loggingIn.then(function() { // We’ve logged in successfully }, function(err) { // Either the login failed, or the password fetch failed }); // NOTE: As of jQuery 1.8, then and pipe are synonymous. // Use `then` for piping if possible.
  • 34. Piping Promises var menuFilePromise = mainWindow.menu('file'); var openFilePromise = menuFilePromise.pipe(function(file) {   return file.openMenu(); }); var menuOpenPromise = openFilePromise.pipe(function(menu) {   return menu.item('open'); }); var itemClickPromise = menuOpenPromise.pipe(function(item) {   return item.click() }); var createDialogPromise = itemClickPromise.pipe(function() {   return window.createDialog("Promises rock!"); });
  • 35. A Promise-y Rocket function launchRocketAt(target) { var rocketDeferred = $.Deferred(); _.extend(rocketDeferred, {x: 0, y: 0, step: 0}); function moveRocket() { // Physics calculations go here... rocketDeferred.notify(step / 10); if (rocketDeferred.step === 10) { rocketDeferred.resolve(); } else { rocketDeferred.step += 1; setTimeout(moveRocket, 50); } } moveRocket(); return rocketDeferred; }
  • 36. Promise Drawbacks • No standard • jQuery, Promises/A, Promises/B... • For maximum benefit, you’ll need wrappers all over the place
  • 38. What is AMD? • Asynchronous Module Definition, a spec • Each module says which modules it needs • The module’s “factory” is called after all of those modules are loaded
  • 39. What is AMD for? • Loading dependencies as needed • Dependency injection (for tests) • Gating features
  • 40. How to use AMD define('myModule', ['jQuery', 'Backbone'], function($, Backbone) { var myModule = { // Define some things... }; // If anyone requires this module, they get this object return myModule; });
  • 41. AMD Drawbacks • No standard • Lots of up-front work • No semantic versioning • Heavyweight tools (RequireJS)
  • 42. Alternatives to AMD • Browserify • Simple syntax: require('./filename'); • Great if you’re into Node + npm • Intended for bundling, not so much for async module loading
  • 43. Conclusion • The next time you’re about to define a function with a callback argument... don’t.
  • 44. Thanks. Questions? @trevorburnham