SlideShare una empresa de Scribd logo
1 de 49
Promises, Promises
                     BY @DOMENIC
Domenic Denicola
•   http://domenic.me
•   https://github.com/domenic
•   https://npmjs.org/~domenic
•   http://slideshare.net/domenicdenicola

Things I’m doing:
• @esdiscuss on Twitter
• The Promises/A+ spec
• HTML5DevConf, NodePDX, NodeConf
                                            @DOMENIC
@DOMENIC
Callbacks are a hack
• They are literally the simplest thing that could work.
• But as a replacement for synchronous control flow, they suck.

• There’s no consistency in callback APIs.
• There’s no guarantees.
• We lose the flow of our code writing callbacks that tie
  together other callbacks.
• We lose the stack-unwinding semantics of exceptions, forcing
  us to handle errors explicitly at every step.
                                                                  @DOMENIC
Promises are the right abstraction
Instead of calling a passed callback, return a promise:

 readFile("file.txt", function (err, result) {
     // continue here…
 });

// becomes

 var promiseForResult = readFile("file.txt");

                                                          @DOMENIC
Promise guarantees
promiseForResult.then(onFulfilled, onRejected);

• Only one of onFulfilled or onRejected will be called.
• onFulfilled will be called with a single fulfillment value (⇔ return value).
• onRejected will be called with a single rejection reason (⇔ thrown exception).
• If the promise is already settled, the handlers will still be called once you
  attach them.
• The handlers will always be called asynchronously.

                                                                       @DOMENIC
Promises can be chained
var transformedPromise = originalPromise.then(onFulfilled, onRejected);

• If the called handler returns a value, transformedPromise will be resolved
  with that value:
  ▫ If the returned value is a promise, we adopt its state.
  ▫ Otherwise, transformedPromise is fulfilled with that value.
• If the called handler throws an exception, transformedPromise will be
  rejected with that exception.

                                                                       @DOMENIC
The Sync ⇔ Async Parallel
 var result, threw = false;

 try {
    result = doSomethingSync();   doSomethingAsync().then(
 } catch (ex) {                      process,
    threw = true;                    handle
    handle(ex);                   );
 }

 if (!threw) process(result);
                                                             @DOMENIC
Case 1: Simple Functional Transform
 var user = getUser();
 var userName = user.name;

// becomes

 var userNamePromise = getUser().then(function (user) {
     return user.name;
 });


                                                          @DOMENIC
Case 2: Reacting with an Exception
 var user = getUser();
 if (user === null)
    throw new Error("null user!");

becomes

 var userPromise = getUser().then(function (user) {
     if (user === null)
        throw new Error("null user!");
     return user;
 });
                                                      @DOMENIC
Case 3: Handling an Exception
 try {
    updateUser(data);
 } catch (ex) {
    console.log("There was an error:", ex);
 }

// becomes

 var updatePromise = updateUser(data).then(undefined, function (ex) {
     console.log("There was an error:", ex);
 });
                                                                    @DOMENIC
Case 4: Rethrowing an Exception
 try {
    updateUser(data);
 } catch (ex) {
    throw new Error("Updating user failed. Details: " + ex.message);
 }

// becomes

 var updatePromise = updateUser(data).then(undefined, function (ex) {
     throw new Error("Updating user failed. Details: " + ex.message);
 });
                                                                       @DOMENIC
Bonus Async Case: Waiting
 var name = promptForNewUserName();
 updateUser({ name: name });
 refreshUI();

// becomes

 promptForNewUserName()
   .then(function (name) {
      return updateUser({ name: name });
   })
   .then(refreshUI);
                                           @DOMENIC
Promises Give You Back Exception Propagation
getUser("Domenic", function (user) {
    getBestFriend(user, function (friend) {
        ui.showBestFriend(friend);
    });
});




                                               @DOMENIC
Promises Give You Back Exception Propagation
getUser("Domenic", function (err, user) {
    if (err) {
       ui.error(err);
    } else {
       getBestFriend(user, function (err, friend) {
           if (err) {
              ui.error(err);
           } else {
              ui.showBestFriend(friend);
           }
       });
    }
});
                                                      @DOMENIC
Promises Give You Back Exception Propagation
getUser("Domenic")
  .then(getBestFriend)
  .then(ui.showBestFriend, ui.error);




                                               @DOMENIC
Promises as First-Class Objects
• Because promises are first-class objects, you can build simple operations on
  them instead of tying callbacks together:

// Fulfills with an array of results, or rejects if any reject
all([getUserData(), getCompanyData()]);

// Fulfills as soon as either completes, or rejects if both reject
any([storeDataOnServer1(), storeDataOnServer2()]);

// If writeFile accepts promises as arguments, and readFile returns one:
writeFile("dest.txt", readFile("source.txt"));
                                                                           @DOMENIC
@DOMENIC
Prehistory
• “Discovered” circa 1989.
• Much of modern promises are inspired by the E programming language.
• They’ve made their way into many languages:
 ▫   .NET’s Task<T>
 ▫   java.util.concurrent.Future
 ▫   Python’s PEP 3148
 ▫   C++ 11’s std::future


                                                              @DOMENIC
CommonJS Promises/A
• Inspired by early implementations: ref_send, Dojo, …
• But…
  ▫ Underspecified
  ▫ Missing key features
  ▫ Often misinterpreted




                                                         @DOMENIC
$.Deferred
jQuery’s $.Deferred is a very buggy attempted implementation, that
entirely misses the sync ⇔ async parallel:
• Multiple fulfillment values and rejection reasons
• Only supports scenario 1 (functional transformation); doesn’t handle
  errors
• Not interoperable with other “thenables.”
• Before 1.8, did not support returning a promise


                                                                 @DOMENIC
All Was Quiet, Until…




                        HORRIBLE LIES!!




                                          @DOMENIC
I Got Angry




              @DOMENIC
Then I Did Something About It




                                @DOMENIC
@DOMENIC
Then Things Got Awesome




                          @DOMENIC
Fast-Forward a Few Months…




                             @DOMENIC
I Think It’s Been a Success
• >20 conformant implementations, with more showing up constantly
  ▫ Even one in ActionScript 3!
• The creation of RSVP.js specifically so that Ember could have
  Promises/A+ compatible promises
• Version 1.1 of the spec almost ready, nailing down some unspecified
  points
• Several other sibling specs under active development: promise creation,
  cancellation, progress, …

                                                                 @DOMENIC
Even the DOM and TC39 are getting in on this
• Alex Russell’s DOMFuture promise library, for possibly using promises in
  future or existing DOM APIs
• Convergence with Mark Miller’s concurrency strawman, for integrating
  promises into the language




                                                                  @DOMENIC
Some practical guidance




                          @DOMENIC
First, Choose a Library
• My top picks:
  ▫ Q, by Kris Kowal and myself: https://github.com/kriskowal/q
  ▫ When.js, by Brian Cavalier: https://github.com/cujojs/when
  ▫ RSVP.js, by Yehuda Katz: https://github.com/tildeio/rsvp.js

• If you ever see a jQuery promise, kill it with fire:

 var realPromise = Q(jQueryPromise);
 var realPromise = when(jQueryPromise);
                                                                  @DOMENIC
Keep The Sync ⇔ Async Parallel In Mind
• Use promises for single operations that can result in fulfillment
  (⇔ returning a value) or rejection (⇔ throwing an exception).

• If you’re ever stuck, ask “how would I structure this code if it
  were synchronous?”
  ▫ The only exception is multiple parallel operations, which has no
    sync counterpart.


                                                                       @DOMENIC
Promises Are Not
• A replacement for events
• A replacement for streams
• A way of doing functional reactive programming

They work together:
• An event can trigger from one part of your UI, causing the event handler
  to trigger a promise-returning function
• A HTTP request function can return a promise for a stream

                                                                  @DOMENIC
The Unhandled Rejection Pitfall
This hits the top of the stack:

 throw new Error("boo!");

This stays inert:

 var promise = doSomething().then(function () {
     throw new Error("boo!");
 });

                                                  @DOMENIC
Avoiding the Unhandled Rejection Pitfall
• Always either:
  ▫ return the promise to your caller;
  ▫ or call .done() on it to signal that any unhandled rejections should explode

function getUserName() {
   return getUser().then(function (user) {
    return user.name;
   });
 }
 getUserName().then(function (userName) {
    console.log("User name: ", userName);
 }).done();                                                                   @DOMENIC
Promise Patterns: try/catch/finally
ui.startSpinner();
getUser("Domenic")
   .then(getBestFriend)
   .then(ui.showBestFriend)
   .catch(ui.error)
   .finally(ui.stopSpinner)
   .done();



                                      @DOMENIC
Promise Patterns: all + spread
Q.all([getUser(), getCompany()]).then(function (results) {
   console.log("user = ", results[0]);
   console.log("company = ", results[1]);
}).done();

Q.all([getUser(), getCompany()]).spread(function (user, company) {
   console.log("user = ", user);
   console.log("company = ", company);
}).done();
                                                                 @DOMENIC
Promise Patterns: map + all
var userIds = ["123", "456", "789"];

Q.all(userIds.map(getUserById))
  .then(function (users) {
     console.log("all the users: ", users);
  })
  .done();


                                              @DOMENIC
Promise Patterns: message sending
var userData = getUserData();
userData
  .then(createUserViewModel)
  .invoke("setStatus", "loaded")
  .done();
userData
  .get("friends")
  .get("0")
  .get("name")
  .then(setBestFriendsNameInUI)
  .done();
                                    @DOMENIC
Promise Patterns: Denodeify
var readFile = Q.denodeify(fs.readFile);
var readDir = Q.denodeify(fs.readdir);
readDir("/tmp")
  .get("0")
  .then(readFile)
  .then(function (data) {
     console.log("The first temporary file contains: ", data);
  })
  .catch(function (error) {
     console.log("One of the steps failed: ", error);
  })
  .done();
                                                                 @DOMENIC
(Bonus round!)




                 @DOMENIC
Coroutines

    “Coroutines are computer program
components that generalize subroutines to
allow multiple entry points for suspending
     and resuming execution at certain
                locations.”
                                     @DOMENIC
Generators = Shallow Coroutines
function* fibonacci() {
  var [prev, curr] = [0, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (n of fibonnaci()) {
  console.log(n);
}                                         @DOMENIC
http://taskjs.org/


task.js: Generators + Promises = Tasks
spawn(function* () {
    var data = yield $.ajax(url);
    $("#result").html(data);
    var status = $("#status").html("Download complete.");
    yield status.fadeIn().promise();
    yield sleep(2000);
    status.fadeOut();
});

                                                            @DOMENIC
task.js Even Works on Exceptions
spawn(function* () {
  var user;
  try {
     user = yield getUser();
  } catch (err) {
     ui.showError(err);
     return;
  }

      ui.updateUser(user);
});
                                   @DOMENIC
Remote Promises
userPromise
  .get("friends")
  .get("0")
  .invoke("calculateFriendshipCoefficient")
  .then(displayInUI)
  .done();

What if … userPromise referred to a remote object?!

                                                      @DOMENIC
https://github.com/kriskowal/q-connection/



Q Connection
• Can connect to web workers, <iframe>s, or web sockets

var Q = require("q");
var Connection = require("q-comm");
var remote = Connection(port, local);

// a promise for a remote object!
var userPromise = remote.getUser();


                                                                        @DOMENIC
Promise Pipelining
• Usual “remote object” systems fall down in a few ways:
  ▫ They would see the first request, and return the entire friends array.
  ▫ They can’t invoke methods that involved closed-over state, only methods
    that you can send over the wire.
  ▫ Workarounds involve complex serialization and rehydration approaches, i.e.
    require coupling the client and the server.
• With promises as the abstraction, we can “pipeline” messages from one
  side to the other, returning the ultimately-desired result.

                                                                     @DOMENIC
• Start using promises in your code: client, server,
                everywhere.
              • Be aware that you want a Promises/A+ compatible
                library—beware jQuery.
              • Generators are almost ready in Firefox, Chrome, and
What’s next     Node.js.
              • Investigate promises for real-time communication with
                Q-Connection.
              • Look forward to promises in the DOM, and maybe some
                syntactic support in ECMAScript 7!




                                                          @DOMENIC

Más contenido relacionado

La actualidad más candente

Asynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & PromisesAsynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & PromisesHùng Nguyễn Huy
 
Concurrency in Golang
Concurrency in GolangConcurrency in Golang
Concurrency in GolangOliver N
 
Grails transactions
Grails   transactionsGrails   transactions
Grails transactionsHusain Dalal
 
RESTful API Testing using Postman, Newman, and Jenkins
RESTful API Testing using Postman, Newman, and JenkinsRESTful API Testing using Postman, Newman, and Jenkins
RESTful API Testing using Postman, Newman, and JenkinsQASymphony
 
Angular 4 and TypeScript
Angular 4 and TypeScriptAngular 4 and TypeScript
Angular 4 and TypeScriptAhmed El-Kady
 
Passive reporting verbs
Passive reporting verbsPassive reporting verbs
Passive reporting verbsEbruKILICASLAN
 
Nestjs MasterClass Slides
Nestjs MasterClass SlidesNestjs MasterClass Slides
Nestjs MasterClass SlidesNir Kaufman
 
Introduction to Go programming
Introduction to Go programmingIntroduction to Go programming
Introduction to Go programmingExotel
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous JavascriptGarrett Welson
 
Angular kickstart slideshare
Angular kickstart   slideshareAngular kickstart   slideshare
Angular kickstart slideshareSaleemMalik52
 
Clean Code II - Dependency Injection
Clean Code II - Dependency InjectionClean Code II - Dependency Injection
Clean Code II - Dependency InjectionTheo Jungeblut
 
Angular data binding
Angular data binding Angular data binding
Angular data binding Sultan Ahmed
 
Introduction to GitHub
Introduction to GitHubIntroduction to GitHub
Introduction to GitHubNishan Bose
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React AlicanteIgnacio Martín
 

La actualidad más candente (20)

Asynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & PromisesAsynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & Promises
 
Concurrency in Golang
Concurrency in GolangConcurrency in Golang
Concurrency in Golang
 
Grails transactions
Grails   transactionsGrails   transactions
Grails transactions
 
RESTful API Testing using Postman, Newman, and Jenkins
RESTful API Testing using Postman, Newman, and JenkinsRESTful API Testing using Postman, Newman, and Jenkins
RESTful API Testing using Postman, Newman, and Jenkins
 
Postman
PostmanPostman
Postman
 
Angular 4 and TypeScript
Angular 4 and TypeScriptAngular 4 and TypeScript
Angular 4 and TypeScript
 
Passive reporting verbs
Passive reporting verbsPassive reporting verbs
Passive reporting verbs
 
Nestjs MasterClass Slides
Nestjs MasterClass SlidesNestjs MasterClass Slides
Nestjs MasterClass Slides
 
Introduction to Go programming
Introduction to Go programmingIntroduction to Go programming
Introduction to Go programming
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous Javascript
 
Angular kickstart slideshare
Angular kickstart   slideshareAngular kickstart   slideshare
Angular kickstart slideshare
 
Cucumber & gherkin language
Cucumber & gherkin languageCucumber & gherkin language
Cucumber & gherkin language
 
Clean Code II - Dependency Injection
Clean Code II - Dependency InjectionClean Code II - Dependency Injection
Clean Code II - Dependency Injection
 
Async js
Async jsAsync js
Async js
 
Callback Function
Callback FunctionCallback Function
Callback Function
 
Angular data binding
Angular data binding Angular data binding
Angular data binding
 
Testing Angular
Testing AngularTesting Angular
Testing Angular
 
Introduction to GitHub
Introduction to GitHubIntroduction to GitHub
Introduction to GitHub
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
 
Git basics
Git basicsGit basics
Git basics
 

Destacado

Boom! Promises/A+ Was Born
Boom! Promises/A+ Was BornBoom! Promises/A+ Was Born
Boom! Promises/A+ Was BornDomenic Denicola
 
Callbacks, promises, generators - asynchronous javascript
Callbacks, promises, generators - asynchronous javascriptCallbacks, promises, generators - asynchronous javascript
Callbacks, promises, generators - asynchronous javascriptŁukasz Kużyński
 
JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6Solution4Future
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises우영 주
 
The State of JavaScript (2015)
The State of JavaScript (2015)The State of JavaScript (2015)
The State of JavaScript (2015)Domenic Denicola
 
How to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards BodiesHow to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards BodiesDomenic Denicola
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript PromisesTomasz Bak
 
Present Simple With Future Meaning
Present Simple With Future MeaningPresent Simple With Future Meaning
Present Simple With Future Meaningjosealmaraz1999
 
Talking about the Future using Present Tenses
Talking about the Future using Present TensesTalking about the Future using Present Tenses
Talking about the Future using Present TensestheLecturette
 
Real World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScriptReal World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScriptDomenic Denicola
 
Creating Truly RESTful APIs
Creating Truly RESTful APIsCreating Truly RESTful APIs
Creating Truly RESTful APIsDomenic Denicola
 
Present tense verbs with future meaning
Present tense verbs with future meaningPresent tense verbs with future meaning
Present tense verbs with future meaningmaleja2028
 
Importance of contract in Islam and legal importance
Importance of contract in Islam and legal importanceImportance of contract in Islam and legal importance
Importance of contract in Islam and legal importanceMuhammad Zeeshan Baloch
 

Destacado (20)

JavaScript Promise
JavaScript PromiseJavaScript Promise
JavaScript Promise
 
Boom! Promises/A+ Was Born
Boom! Promises/A+ Was BornBoom! Promises/A+ Was Born
Boom! Promises/A+ Was Born
 
Callbacks, promises, generators - asynchronous javascript
Callbacks, promises, generators - asynchronous javascriptCallbacks, promises, generators - asynchronous javascript
Callbacks, promises, generators - asynchronous javascript
 
JavaScript on the Desktop
JavaScript on the DesktopJavaScript on the Desktop
JavaScript on the Desktop
 
JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
The State of JavaScript (2015)
The State of JavaScript (2015)The State of JavaScript (2015)
The State of JavaScript (2015)
 
How to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards BodiesHow to Win Friends and Influence Standards Bodies
How to Win Friends and Influence Standards Bodies
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
Promises
Promises Promises
Promises
 
Present Simple With Future Meaning
Present Simple With Future MeaningPresent Simple With Future Meaning
Present Simple With Future Meaning
 
Talking about the Future using Present Tenses
Talking about the Future using Present TensesTalking about the Future using Present Tenses
Talking about the Future using Present Tenses
 
Promises Javascript
Promises JavascriptPromises Javascript
Promises Javascript
 
Real World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScriptReal World Windows 8 Apps in JavaScript
Real World Windows 8 Apps in JavaScript
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
 
Creating Truly RESTful APIs
Creating Truly RESTful APIsCreating Truly RESTful APIs
Creating Truly RESTful APIs
 
Present tense verbs with future meaning
Present tense verbs with future meaningPresent tense verbs with future meaning
Present tense verbs with future meaning
 
The Final Frontier
The Final FrontierThe Final Frontier
The Final Frontier
 
Client-Side Packages
Client-Side PackagesClient-Side Packages
Client-Side Packages
 
Importance of contract in Islam and legal importance
Importance of contract in Islam and legal importanceImportance of contract in Islam and legal importance
Importance of contract in Islam and legal importance
 

Similar a Promises Simplify Async Code

The Promised Land (in Angular)
The Promised Land (in Angular)The Promised Land (in Angular)
The Promised Land (in Angular)Domenic Denicola
 
Unit Testing for Great Justice
Unit Testing for Great JusticeUnit Testing for Great Justice
Unit Testing for Great JusticeDomenic Denicola
 
Javascript Promises/Q Library
Javascript Promises/Q LibraryJavascript Promises/Q Library
Javascript Promises/Q Libraryasync_io
 
Javascript essential-pattern
Javascript essential-patternJavascript essential-pattern
Javascript essential-pattern偉格 高
 
An opinionated intro to Node.js - devrupt hospitality hackathon
An opinionated intro to Node.js - devrupt hospitality hackathonAn opinionated intro to Node.js - devrupt hospitality hackathon
An opinionated intro to Node.js - devrupt hospitality hackathonLuciano Mammino
 
Promises look into the async future
Promises look into the async futurePromises look into the async future
Promises look into the async futureslicejs
 
Realm Mobile Database - An Introduction
Realm Mobile Database - An IntroductionRealm Mobile Database - An Introduction
Realm Mobile Database - An IntroductionKnoldus Inc.
 
Getting Comfortable with JS Promises
Getting Comfortable with JS PromisesGetting Comfortable with JS Promises
Getting Comfortable with JS PromisesAsa Kusuma
 
Web development basics (Part-6)
Web development basics (Part-6)Web development basics (Part-6)
Web development basics (Part-6)Rajat Pratap Singh
 
Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications  Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications Juliana Lucena
 
Hands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkHands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkRyan Weaver
 
Asynchronous development in JavaScript
Asynchronous development  in JavaScriptAsynchronous development  in JavaScript
Asynchronous development in JavaScriptAmitai Barnea
 
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 callsHuy Hoàng Phạm
 

Similar a Promises Simplify Async Code (20)

Domains!
Domains!Domains!
Domains!
 
The Promised Land (in Angular)
The Promised Land (in Angular)The Promised Land (in Angular)
The Promised Land (in Angular)
 
Unit Testing for Great Justice
Unit Testing for Great JusticeUnit Testing for Great Justice
Unit Testing for Great Justice
 
You promise?
You promise?You promise?
You promise?
 
Sane Async Patterns
Sane Async PatternsSane Async Patterns
Sane Async Patterns
 
Javascript Promises/Q Library
Javascript Promises/Q LibraryJavascript Promises/Q Library
Javascript Promises/Q Library
 
Javascript essential-pattern
Javascript essential-patternJavascript essential-pattern
Javascript essential-pattern
 
An opinionated intro to Node.js - devrupt hospitality hackathon
An opinionated intro to Node.js - devrupt hospitality hackathonAn opinionated intro to Node.js - devrupt hospitality hackathon
An opinionated intro to Node.js - devrupt hospitality hackathon
 
Promises look into the async future
Promises look into the async futurePromises look into the async future
Promises look into the async future
 
[2015/2016] JavaScript
[2015/2016] JavaScript[2015/2016] JavaScript
[2015/2016] JavaScript
 
How to keep promises
How to keep promisesHow to keep promises
How to keep promises
 
ES6: The Awesome Parts
ES6: The Awesome PartsES6: The Awesome Parts
ES6: The Awesome Parts
 
JavaScript
JavaScriptJavaScript
JavaScript
 
Realm Mobile Database - An Introduction
Realm Mobile Database - An IntroductionRealm Mobile Database - An Introduction
Realm Mobile Database - An Introduction
 
Getting Comfortable with JS Promises
Getting Comfortable with JS PromisesGetting Comfortable with JS Promises
Getting Comfortable with JS Promises
 
Web development basics (Part-6)
Web development basics (Part-6)Web development basics (Part-6)
Web development basics (Part-6)
 
Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications  Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications
 
Hands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkHands-on with the Symfony2 Framework
Hands-on with the Symfony2 Framework
 
Asynchronous development in JavaScript
Asynchronous development  in JavaScriptAsynchronous development  in JavaScript
Asynchronous development in JavaScript
 
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
 

Más de Domenic Denicola

Más de Domenic Denicola (8)

Async Frontiers
Async FrontiersAsync Frontiers
Async Frontiers
 
The jsdom
The jsdomThe jsdom
The jsdom
 
ES6 in Real Life
ES6 in Real LifeES6 in Real Life
ES6 in Real Life
 
Streams for the Web
Streams for the WebStreams for the Web
Streams for the Web
 
After Return of the Jedi
After Return of the JediAfter Return of the Jedi
After Return of the Jedi
 
The State of JavaScript
The State of JavaScriptThe State of JavaScript
The State of JavaScript
 
The Extensible Web
The Extensible WebThe Extensible Web
The Extensible Web
 
Understanding the Node.js Platform
Understanding the Node.js PlatformUnderstanding the Node.js Platform
Understanding the Node.js Platform
 

Último

A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 

Último (20)

A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 

Promises Simplify Async Code

  • 1. Promises, Promises BY @DOMENIC
  • 2. Domenic Denicola • http://domenic.me • https://github.com/domenic • https://npmjs.org/~domenic • http://slideshare.net/domenicdenicola Things I’m doing: • @esdiscuss on Twitter • The Promises/A+ spec • HTML5DevConf, NodePDX, NodeConf @DOMENIC
  • 4. Callbacks are a hack • They are literally the simplest thing that could work. • But as a replacement for synchronous control flow, they suck. • There’s no consistency in callback APIs. • There’s no guarantees. • We lose the flow of our code writing callbacks that tie together other callbacks. • We lose the stack-unwinding semantics of exceptions, forcing us to handle errors explicitly at every step. @DOMENIC
  • 5. Promises are the right abstraction Instead of calling a passed callback, return a promise: readFile("file.txt", function (err, result) { // continue here… }); // becomes var promiseForResult = readFile("file.txt"); @DOMENIC
  • 6. Promise guarantees promiseForResult.then(onFulfilled, onRejected); • Only one of onFulfilled or onRejected will be called. • onFulfilled will be called with a single fulfillment value (⇔ return value). • onRejected will be called with a single rejection reason (⇔ thrown exception). • If the promise is already settled, the handlers will still be called once you attach them. • The handlers will always be called asynchronously. @DOMENIC
  • 7. Promises can be chained var transformedPromise = originalPromise.then(onFulfilled, onRejected); • If the called handler returns a value, transformedPromise will be resolved with that value: ▫ If the returned value is a promise, we adopt its state. ▫ Otherwise, transformedPromise is fulfilled with that value. • If the called handler throws an exception, transformedPromise will be rejected with that exception. @DOMENIC
  • 8. The Sync ⇔ Async Parallel var result, threw = false; try { result = doSomethingSync(); doSomethingAsync().then( } catch (ex) { process, threw = true; handle handle(ex); ); } if (!threw) process(result); @DOMENIC
  • 9. Case 1: Simple Functional Transform var user = getUser(); var userName = user.name; // becomes var userNamePromise = getUser().then(function (user) { return user.name; }); @DOMENIC
  • 10. Case 2: Reacting with an Exception var user = getUser(); if (user === null) throw new Error("null user!"); becomes var userPromise = getUser().then(function (user) { if (user === null) throw new Error("null user!"); return user; }); @DOMENIC
  • 11. Case 3: Handling an Exception try { updateUser(data); } catch (ex) { console.log("There was an error:", ex); } // becomes var updatePromise = updateUser(data).then(undefined, function (ex) { console.log("There was an error:", ex); }); @DOMENIC
  • 12. Case 4: Rethrowing an Exception try { updateUser(data); } catch (ex) { throw new Error("Updating user failed. Details: " + ex.message); } // becomes var updatePromise = updateUser(data).then(undefined, function (ex) { throw new Error("Updating user failed. Details: " + ex.message); }); @DOMENIC
  • 13. Bonus Async Case: Waiting var name = promptForNewUserName(); updateUser({ name: name }); refreshUI(); // becomes promptForNewUserName() .then(function (name) { return updateUser({ name: name }); }) .then(refreshUI); @DOMENIC
  • 14. Promises Give You Back Exception Propagation getUser("Domenic", function (user) { getBestFriend(user, function (friend) { ui.showBestFriend(friend); }); }); @DOMENIC
  • 15. Promises Give You Back Exception Propagation getUser("Domenic", function (err, user) { if (err) { ui.error(err); } else { getBestFriend(user, function (err, friend) { if (err) { ui.error(err); } else { ui.showBestFriend(friend); } }); } }); @DOMENIC
  • 16. Promises Give You Back Exception Propagation getUser("Domenic") .then(getBestFriend) .then(ui.showBestFriend, ui.error); @DOMENIC
  • 17. Promises as First-Class Objects • Because promises are first-class objects, you can build simple operations on them instead of tying callbacks together: // Fulfills with an array of results, or rejects if any reject all([getUserData(), getCompanyData()]); // Fulfills as soon as either completes, or rejects if both reject any([storeDataOnServer1(), storeDataOnServer2()]); // If writeFile accepts promises as arguments, and readFile returns one: writeFile("dest.txt", readFile("source.txt")); @DOMENIC
  • 19. Prehistory • “Discovered” circa 1989. • Much of modern promises are inspired by the E programming language. • They’ve made their way into many languages: ▫ .NET’s Task<T> ▫ java.util.concurrent.Future ▫ Python’s PEP 3148 ▫ C++ 11’s std::future @DOMENIC
  • 20. CommonJS Promises/A • Inspired by early implementations: ref_send, Dojo, … • But… ▫ Underspecified ▫ Missing key features ▫ Often misinterpreted @DOMENIC
  • 21. $.Deferred jQuery’s $.Deferred is a very buggy attempted implementation, that entirely misses the sync ⇔ async parallel: • Multiple fulfillment values and rejection reasons • Only supports scenario 1 (functional transformation); doesn’t handle errors • Not interoperable with other “thenables.” • Before 1.8, did not support returning a promise @DOMENIC
  • 22. All Was Quiet, Until… HORRIBLE LIES!! @DOMENIC
  • 23. I Got Angry @DOMENIC
  • 24. Then I Did Something About It @DOMENIC
  • 26. Then Things Got Awesome @DOMENIC
  • 27. Fast-Forward a Few Months… @DOMENIC
  • 28. I Think It’s Been a Success • >20 conformant implementations, with more showing up constantly ▫ Even one in ActionScript 3! • The creation of RSVP.js specifically so that Ember could have Promises/A+ compatible promises • Version 1.1 of the spec almost ready, nailing down some unspecified points • Several other sibling specs under active development: promise creation, cancellation, progress, … @DOMENIC
  • 29. Even the DOM and TC39 are getting in on this • Alex Russell’s DOMFuture promise library, for possibly using promises in future or existing DOM APIs • Convergence with Mark Miller’s concurrency strawman, for integrating promises into the language @DOMENIC
  • 31. First, Choose a Library • My top picks: ▫ Q, by Kris Kowal and myself: https://github.com/kriskowal/q ▫ When.js, by Brian Cavalier: https://github.com/cujojs/when ▫ RSVP.js, by Yehuda Katz: https://github.com/tildeio/rsvp.js • If you ever see a jQuery promise, kill it with fire: var realPromise = Q(jQueryPromise); var realPromise = when(jQueryPromise); @DOMENIC
  • 32. Keep The Sync ⇔ Async Parallel In Mind • Use promises for single operations that can result in fulfillment (⇔ returning a value) or rejection (⇔ throwing an exception). • If you’re ever stuck, ask “how would I structure this code if it were synchronous?” ▫ The only exception is multiple parallel operations, which has no sync counterpart. @DOMENIC
  • 33. Promises Are Not • A replacement for events • A replacement for streams • A way of doing functional reactive programming They work together: • An event can trigger from one part of your UI, causing the event handler to trigger a promise-returning function • A HTTP request function can return a promise for a stream @DOMENIC
  • 34. The Unhandled Rejection Pitfall This hits the top of the stack: throw new Error("boo!"); This stays inert: var promise = doSomething().then(function () { throw new Error("boo!"); }); @DOMENIC
  • 35. Avoiding the Unhandled Rejection Pitfall • Always either: ▫ return the promise to your caller; ▫ or call .done() on it to signal that any unhandled rejections should explode function getUserName() { return getUser().then(function (user) { return user.name; }); } getUserName().then(function (userName) { console.log("User name: ", userName); }).done(); @DOMENIC
  • 36. Promise Patterns: try/catch/finally ui.startSpinner(); getUser("Domenic") .then(getBestFriend) .then(ui.showBestFriend) .catch(ui.error) .finally(ui.stopSpinner) .done(); @DOMENIC
  • 37. Promise Patterns: all + spread Q.all([getUser(), getCompany()]).then(function (results) { console.log("user = ", results[0]); console.log("company = ", results[1]); }).done(); Q.all([getUser(), getCompany()]).spread(function (user, company) { console.log("user = ", user); console.log("company = ", company); }).done(); @DOMENIC
  • 38. Promise Patterns: map + all var userIds = ["123", "456", "789"]; Q.all(userIds.map(getUserById)) .then(function (users) { console.log("all the users: ", users); }) .done(); @DOMENIC
  • 39. Promise Patterns: message sending var userData = getUserData(); userData .then(createUserViewModel) .invoke("setStatus", "loaded") .done(); userData .get("friends") .get("0") .get("name") .then(setBestFriendsNameInUI) .done(); @DOMENIC
  • 40. Promise Patterns: Denodeify var readFile = Q.denodeify(fs.readFile); var readDir = Q.denodeify(fs.readdir); readDir("/tmp") .get("0") .then(readFile) .then(function (data) { console.log("The first temporary file contains: ", data); }) .catch(function (error) { console.log("One of the steps failed: ", error); }) .done(); @DOMENIC
  • 41. (Bonus round!) @DOMENIC
  • 42. Coroutines “Coroutines are computer program components that generalize subroutines to allow multiple entry points for suspending and resuming execution at certain locations.” @DOMENIC
  • 43. Generators = Shallow Coroutines function* fibonacci() { var [prev, curr] = [0, 1]; while (true) { [prev, curr] = [curr, prev + curr]; yield curr; } } for (n of fibonnaci()) { console.log(n); } @DOMENIC
  • 44. http://taskjs.org/ task.js: Generators + Promises = Tasks spawn(function* () { var data = yield $.ajax(url); $("#result").html(data); var status = $("#status").html("Download complete."); yield status.fadeIn().promise(); yield sleep(2000); status.fadeOut(); }); @DOMENIC
  • 45. task.js Even Works on Exceptions spawn(function* () { var user; try { user = yield getUser(); } catch (err) { ui.showError(err); return; } ui.updateUser(user); }); @DOMENIC
  • 46. Remote Promises userPromise .get("friends") .get("0") .invoke("calculateFriendshipCoefficient") .then(displayInUI) .done(); What if … userPromise referred to a remote object?! @DOMENIC
  • 47. https://github.com/kriskowal/q-connection/ Q Connection • Can connect to web workers, <iframe>s, or web sockets var Q = require("q"); var Connection = require("q-comm"); var remote = Connection(port, local); // a promise for a remote object! var userPromise = remote.getUser(); @DOMENIC
  • 48. Promise Pipelining • Usual “remote object” systems fall down in a few ways: ▫ They would see the first request, and return the entire friends array. ▫ They can’t invoke methods that involved closed-over state, only methods that you can send over the wire. ▫ Workarounds involve complex serialization and rehydration approaches, i.e. require coupling the client and the server. • With promises as the abstraction, we can “pipeline” messages from one side to the other, returning the ultimately-desired result. @DOMENIC
  • 49. • Start using promises in your code: client, server, everywhere. • Be aware that you want a Promises/A+ compatible library—beware jQuery. • Generators are almost ready in Firefox, Chrome, and What’s next Node.js. • Investigate promises for real-time communication with Q-Connection. • Look forward to promises in the DOM, and maybe some syntactic support in ECMAScript 7! @DOMENIC

Notas del editor

  1. Hook: how many used promises?jQuery promises or real promises?Want to talk about this in three parts: a ground-up view of the promise abstraction; a historical perspective on recent developments; and a practical guide to using them in your code.
  2. What I really mean by this is “callback-accepting functions are a hack.”
  3. First benefit: separating outputs from inputs.
  4. - Consistency gains: never call back with more than one fulfillment value or rejection reason.
  5. Just like a series of imperative statements.
  6. And yet, we lived with it.
  7. Spec development process through GitHub issue trackerPull requests, implementers weighing in, bugs opened by randoms, etc.Test suite!
  8. Q has:Large, powerful API surfaceAdapters for Node.jsProgress supportSome support for long stack traces