SlideShare a Scribd company logo
1 of 42
Download to read offline
The
Promised
Land
by @domenic
in
http://domenic.me
https://github.com/domenic
https://npmjs.org/~domenic
http://slideshare.net/domenicdenicola
THINGS I’M DOING
 The Promises/A+ and ES6 promise specs
 Working on Q
 The Extensible Web Manifesto
Domenic Denicola
Angular is enlightened
• Like most other client-side frameworks these days, Angular uses promises for
everything async:
• $timeout
• $http + response interceptors
• $resource
• $routeProvider.when
• Its built-in promise library, $q, is pretty good.
• But first, let’s take a step back and start from the beginning.
Promises, in General
Web programming is async
• I/O (like XMLHttpRequest, IndexedDB, or waiting for the user to click) takes time
• We have only a single thread
• We don’t want to freeze the tab while we do I/O
• So we tell the browser:
• Go do your I/O
• When you’re done, run this code
• In the meantime, let’s move on to some other code
Async with callbacks
// Ask for permission to show notifications
Notification.requestPermission(function (result) {
// When the user clicks yes or no, this code runs.
if (result === 'denied') {
console.log('user clicked no');
} else {
console.log('permission granted!');
}
});
// But in the meantime, this code continues to run.
console.log("Waiting for the user...");
Async with events
var request = indexedDB.open("myDatabase");
request.onsuccess = function () {
console.log('opened!');
};
request.onerror = function () {
console.log('failed');
};
console.log("This code runs before either of those");
Async with WTFBBQ
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (this.readyState === this.DONE) {
if (this.status === 200) {
console.log("got the data!" + this.responseText);
} else {
console.log("an error happened!");
}
}
};
xhr.open("GET", "somefile.json");
xhr.send();
These APIs 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.
• 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.
Instead of calling a passed callback, return a promise:
var promiseForTemplate = $http.get("template.html");
promiseForTemplate.then(
function (template) {
// use template
},
function (err) {
// couldn’t get the template
});
Promises are the right abstraction
function getPromiseFor5() {
var d = $q.defer();
d.resolve(5);
return d.promise;
}
getPromiseFor5().then(function (v) {
console.log('this will be 5: ' + v);
});
Creating a promise
function getPromiseFor5After1Second() {
var d = $q.defer();
setTimeout(function () {
d.resolve(5);
}, 1000);
return d.promise;
}
getPromiseFor5After1Second().then(function (v) {
// this code only gets run after one second
console.log('this will be 5: ' + v);
});
Creating a promise (more advanced)
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.
Promise guarantees
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.
Promises can be chained
var result;
try {
result = process(getInput());
} catch (ex) {
result = handleError(ex);
}
var resultPromise =
getInputPromise()
.then(processAsync)
.then(undefined, handleErrorAsync);
The sync ⇔ async parallel
var result;
try {
result = process(getInput());
} catch (ex) {
result = handleError(ex);
}
var resultPromise =
getInputPromise()
.then(processAsync)
.catch(handleErrorAsync);
The sync ⇔ async parallel
Case 1: simple functional transform
var user = getUser();
var userName = user.name;
// becomes
var userNamePromise = getUser().then(function (user) {
return user.name;
});
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;
});
Case 3: handling an exception
try {
updateUser(data);
} catch (ex) {
console.log("There was an error:", ex);
}
// becomes
var updatePromise = updateUser(data).catch(function (ex) {
console.log("There was an error:", ex);
});
Case 4: rethrowing an exception
try {
updateUser(data);
} catch (ex) {
throw new Error("Updating user failed. Details: " + ex.message);
}
// becomes
var updatePromise = updateUser(data).catch(function (ex) {
throw new Error("Updating user failed. Details: " + ex.message);
});
var name = promptForNewUserName(userId);
updateUser({ id: userId, name: name });
refreshUI();
// becomes
promptForNewUserName(userId)
.then(function (name) {
return updateUser({ id: userId, name: name });
})
.then(refreshUI);
Bonus async case: waiting
Key features
In practice, here are some key capabilities promises give you:
• They are guaranteed to always be async.
• They provide an asynchronous analog of exception propagation.
• Because they are first-class objects, you can combine them easily and powerfully.
• They allow easy creation of reusable abstractions.
Always async
function getUser(userName, onSuccess, onError) {
if (cache.has(userName)) {
onSuccess(cache.get(userName));
} else {
$.ajax("/user?" + userName, {
success: onSuccess,
error: onError
});
}
}
Always async
console.log("1");
getUser("ddenicola", function (user) {
console.log(user.firstName);
});
console.log("2");
// 1, 2, Domenic
Always async
console.log("1");
getUser("ddenicola", function (user) {
console.log(user.firstName);
});
console.log("2");
// 1, Domenic, 2
Always async
function getUser(userName) {
if (cache.has(userName)) {
return $q.when(cache.get(userName));
} else {
return $http.get("/user?" + userName);
}
}
Always async
console.log("1");
getUser("ddenicola“).then(function (user) {
console.log(user.firstName);
});
console.log("2");
// 1, 2, Domenic (every time!)
getUser("Domenic", function (user) {
getBestFriend(user, function (friend) {
ui.showBestFriend(friend);
});
});
Async “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, function (err, friend) {
if (err) {
ui.error(err);
}
});
}
});
}
});
Async “exception propagation”
getUser("Domenic")
.then(getBestFriend)
.then(ui.showBestFriend)
.catch(ui.error);
Async “exception propagation”
Because promises are first-class objects, you can build simple operations on them instead of tying callbacks
together:
// Fulfills with an array of results when both fulfill, or rejects if either reject
all([getUserData(), getCompanyData()]);
// Fulfills with single result as soon as either fulfills, or rejects if both reject
any([storeDataOnServer1(), storeDataOnServer2()]);
// If writeFile accepts promises as arguments, and readFile returns one:
writeFile("dest.txt", readFile("source.txt"));
Promises as first-class objects
Building promise abstractions
function timer(promise, ms) {
var deferred = $q.defer();
promise.then(deferred.resolve, deferred.reject);
setTimeout(function () {
deferred.reject(new Error("oops timed out"));
}, ms);
return deferred.promise;
}
function httpGetWithTimer(url, ms) {
return timer($http.get(url), ms);
}
Building promise abstractions
function retry(operation, maxTimes) {
return operation().catch(function (reason) {
if (maxTimes === 0) {
throw reason;
}
return retry(operation, maxTimes - 1);
});
}
function httpGetWithRetry(url, maxTimes) {
return retry(function () { return $http.get(url); }, maxTimes);
}
Promises, in Angular
The digest cycle
function MyController($scope) {
$scope.text = "loading";
$scope.doThing = function () {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (this.readyState === this.DONE && this.status === 200) {
$scope.text = this.responseText;
}
};
xhr.open("GET", "somefile.json");
xhr.send();
};
}
// Doesn’t work, because the callback function is outside the digest cycle!
function MyController($scope) {
$scope.text = "loading";
$scope.doThing = function () {
jQuery.get("somefile.json").then(function (responseText) {
$scope.text = responseText;
});
};
}
// Still doesn't work: same problem
function MyController($scope) {
$scope.text = "loading";
$scope.doThing = function () {
jQuery.get("somefile.json").then(function (responseText) {
$scope.apply(function () {
$scope.text = responseText;
});
});
};
}
// Works, but WTF
function MyController($scope, $http) {
$scope.text = "loading";
$scope.doThing = function () {
$http.get("somefile.json").then(function (response) {
$scope.text = response.data;
});
};
}
// Works! Angular’s promises are integrated into the digest cycle
Useful things
• $q.all([promise1, promise2, promise3]).then(function (threeElements) { … });
• $q.all({ a: promiseA, b: promise }).then(function (twoProperties) { … });
• Progress callbacks:
• deferred.notify(value)
• promise.then(undefined, undefined, onProgress)
• But, use sparingly, and be careful
• $q.when(otherThenable), e.g. for jQuery “promises”
• promise.finally(function () {
// happens on either success or failure
});
Gotchas
• Issue 7992: catching thrown errors causes them to be logged anyway
• Writing reusable libraries that vend $q promises is hard
• $q is coupled to Angular’s dependency injection framework
• You have to create an Angular module, which has limited audience
• Angular promises are not as full-featured as other libraries:
• Check out Q or Bluebird
• But to get the digest-cycle magic, you need qPromise.finally($scope.apply).
• Deferreds are kind of lame compared to the ES6 Promise constructor.
• Progress callbacks are problematic.
Thanks!
promisesaplus.com
@promisesaplus

More Related Content

What's hot

Avoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jsAvoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jscacois
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript PromisesTomasz Bak
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptjnewmanux
 
Javascript Promises/Q Library
Javascript Promises/Q LibraryJavascript Promises/Q Library
Javascript Promises/Q Libraryasync_io
 
Callbacks and control flow in Node js
Callbacks and control flow in Node jsCallbacks and control flow in Node js
Callbacks and control flow in Node jsThomas Roch
 
Java Script Promise
Java Script PromiseJava Script Promise
Java Script PromiseAlok Guha
 
Practical JavaScript Promises
Practical JavaScript PromisesPractical JavaScript Promises
Practical JavaScript PromisesAsa Kusuma
 
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...Domenic Denicola
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous phpWim Godden
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016Manoj Kumar
 
Web Crawling with NodeJS
Web Crawling with NodeJSWeb Crawling with NodeJS
Web Crawling with NodeJSSylvain Zimmer
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I thinkWim Godden
 
Getting Comfortable with JS Promises
Getting Comfortable with JS PromisesGetting Comfortable with JS Promises
Getting Comfortable with JS PromisesAsa Kusuma
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is hereSebastiano Armeli
 
Asynchronous programming patterns in Perl
Asynchronous programming patterns in PerlAsynchronous programming patterns in Perl
Asynchronous programming patterns in Perldeepfountainconsulting
 

What's hot (20)

JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
Domains!
Domains!Domains!
Domains!
 
Promises, Promises
Promises, PromisesPromises, Promises
Promises, Promises
 
Avoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jsAvoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.js
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScript
 
Javascript Promises/Q Library
Javascript Promises/Q LibraryJavascript Promises/Q Library
Javascript Promises/Q Library
 
ES6: The Awesome Parts
ES6: The Awesome PartsES6: The Awesome Parts
ES6: The Awesome Parts
 
Callbacks and control flow in Node js
Callbacks and control flow in Node jsCallbacks and control flow in Node js
Callbacks and control flow in Node js
 
Java Script Promise
Java Script PromiseJava Script Promise
Java Script Promise
 
Practical JavaScript Promises
Practical JavaScript PromisesPractical JavaScript Promises
Practical JavaScript Promises
 
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...
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous php
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 
Web Crawling with NodeJS
Web Crawling with NodeJSWeb Crawling with NodeJS
Web Crawling with NodeJS
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
 
Getting Comfortable with JS Promises
Getting Comfortable with JS PromisesGetting Comfortable with JS Promises
Getting Comfortable with JS Promises
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is here
 
Asynchronous programming patterns in Perl
Asynchronous programming patterns in PerlAsynchronous programming patterns in Perl
Asynchronous programming patterns in Perl
 

Similar to The Promised Land (in Angular)

Async js - Nemetschek Presentaion @ HackBulgaria
Async js - Nemetschek Presentaion @ HackBulgariaAsync js - Nemetschek Presentaion @ HackBulgaria
Async js - Nemetschek Presentaion @ HackBulgariaHackBulgaria
 
Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13Jason Lotito
 
Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesAnkit Rastogi
 
Promises look into the async future
Promises look into the async futurePromises look into the async future
Promises look into the async futureslicejs
 
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
 
AngularJS, More Than Directives !
AngularJS, More Than Directives !AngularJS, More Than Directives !
AngularJS, More Than Directives !Gaurav Behere
 
OSCON - ES6 metaprogramming unleashed
OSCON -  ES6 metaprogramming unleashedOSCON -  ES6 metaprogramming unleashed
OSCON - ES6 metaprogramming unleashedJavier Arias Losada
 
Google App Engine Developer - Day3
Google App Engine Developer - Day3Google App Engine Developer - Day3
Google App Engine Developer - Day3Simon Su
 
JavaScript Interview Questions 2023
JavaScript Interview Questions 2023JavaScript Interview Questions 2023
JavaScript Interview Questions 2023Laurence Svekis ✔
 
New improvements for web developers - frontend.fi, Helsinki
New improvements for web developers - frontend.fi, HelsinkiNew improvements for web developers - frontend.fi, Helsinki
New improvements for web developers - frontend.fi, HelsinkiRobert Nyman
 
Promises, promises, and then observables
Promises, promises, and then observablesPromises, promises, and then observables
Promises, promises, and then observablesStefan Charsley
 
What's new in jQuery 1.5
What's new in jQuery 1.5What's new in jQuery 1.5
What's new in jQuery 1.5Martin Kleppe
 
Angular promises and http
Angular promises and httpAngular promises and http
Angular promises and httpAlexe Bogdan
 
Service worker: discover the next web game changer
Service worker: discover the next web game changerService worker: discover the next web game changer
Service worker: discover the next web game changerSandro Paganotti
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5arajivmordani
 

Similar to The Promised Land (in Angular) (20)

Sane Async Patterns
Sane Async PatternsSane Async Patterns
Sane Async Patterns
 
Async js - Nemetschek Presentaion @ HackBulgaria
Async js - Nemetschek Presentaion @ HackBulgariaAsync js - Nemetschek Presentaion @ HackBulgaria
Async js - Nemetschek Presentaion @ HackBulgaria
 
Parse Advanced
Parse AdvancedParse Advanced
Parse Advanced
 
Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13
 
Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practices
 
Promises look into the async future
Promises look into the async futurePromises look into the async future
Promises look into the async future
 
JavaScript Lessons 2023
JavaScript Lessons 2023JavaScript Lessons 2023
JavaScript Lessons 2023
 
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
 
You promise?
You promise?You promise?
You promise?
 
AngularJS, More Than Directives !
AngularJS, More Than Directives !AngularJS, More Than Directives !
AngularJS, More Than Directives !
 
Java script for web developer
Java script for web developerJava script for web developer
Java script for web developer
 
OSCON - ES6 metaprogramming unleashed
OSCON -  ES6 metaprogramming unleashedOSCON -  ES6 metaprogramming unleashed
OSCON - ES6 metaprogramming unleashed
 
Google App Engine Developer - Day3
Google App Engine Developer - Day3Google App Engine Developer - Day3
Google App Engine Developer - Day3
 
JavaScript Interview Questions 2023
JavaScript Interview Questions 2023JavaScript Interview Questions 2023
JavaScript Interview Questions 2023
 
New improvements for web developers - frontend.fi, Helsinki
New improvements for web developers - frontend.fi, HelsinkiNew improvements for web developers - frontend.fi, Helsinki
New improvements for web developers - frontend.fi, Helsinki
 
Promises, promises, and then observables
Promises, promises, and then observablesPromises, promises, and then observables
Promises, promises, and then observables
 
What's new in jQuery 1.5
What's new in jQuery 1.5What's new in jQuery 1.5
What's new in jQuery 1.5
 
Angular promises and http
Angular promises and httpAngular promises and http
Angular promises and http
 
Service worker: discover the next web game changer
Service worker: discover the next web game changerService worker: discover the next web game changer
Service worker: discover the next web game changer
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5a
 

More from Domenic Denicola

More from Domenic Denicola (15)

The State of JavaScript (2015)
The State of JavaScript (2015)The State of JavaScript (2015)
The State of JavaScript (2015)
 
The jsdom
The jsdomThe jsdom
The jsdom
 
The Final Frontier
The Final FrontierThe Final Frontier
The Final Frontier
 
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
 
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
 
The Extensible Web
The Extensible WebThe Extensible Web
The Extensible Web
 
Client-Side Packages
Client-Side PackagesClient-Side Packages
Client-Side Packages
 
Creating Truly RESTful APIs
Creating Truly RESTful APIsCreating Truly RESTful APIs
Creating Truly RESTful APIs
 
JavaScript on the Desktop
JavaScript on the DesktopJavaScript on the Desktop
JavaScript on the Desktop
 
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
 
Unit Testing for Great Justice
Unit Testing for Great JusticeUnit Testing for Great Justice
Unit Testing for Great Justice
 
Understanding the Node.js Platform
Understanding the Node.js PlatformUnderstanding the Node.js Platform
Understanding the Node.js Platform
 

Recently uploaded

Cloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial DataCloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial DataSafe Software
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfAijun Zhang
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...Aggregage
 
Babel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptxBabel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptxYounusS2
 
Spring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdfSpring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdfAnna Loughnan Colquhoun
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1DianaGray10
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPathCommunity
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfinfogdgmi
 
PicPay - GenAI Finance Assistant - ChatGPT for Customer Service
PicPay - GenAI Finance Assistant - ChatGPT for Customer ServicePicPay - GenAI Finance Assistant - ChatGPT for Customer Service
PicPay - GenAI Finance Assistant - ChatGPT for Customer ServiceRenan Moreira de Oliveira
 
Introduction to Quantum Computing
Introduction to Quantum ComputingIntroduction to Quantum Computing
Introduction to Quantum ComputingGDSC PJATK
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Websitedgelyza
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsSeth Reyes
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IES VE
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UbiTrack UK
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding TeamAdam Moalla
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxMatsuo Lab
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024D Cloud Solutions
 
Things you didn't know you can use in your Salesforce
Things you didn't know you can use in your SalesforceThings you didn't know you can use in your Salesforce
Things you didn't know you can use in your SalesforceMartin Humpolec
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.YounusS2
 

Recently uploaded (20)

Cloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial DataCloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial Data
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdf
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
 
Babel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptxBabel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptx
 
Spring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdfSpring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdf
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation Developers
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdf
 
PicPay - GenAI Finance Assistant - ChatGPT for Customer Service
PicPay - GenAI Finance Assistant - ChatGPT for Customer ServicePicPay - GenAI Finance Assistant - ChatGPT for Customer Service
PicPay - GenAI Finance Assistant - ChatGPT for Customer Service
 
Introduction to Quantum Computing
Introduction to Quantum ComputingIntroduction to Quantum Computing
Introduction to Quantum Computing
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Website
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and Hazards
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptx
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024
 
Things you didn't know you can use in your Salesforce
Things you didn't know you can use in your SalesforceThings you didn't know you can use in your Salesforce
Things you didn't know you can use in your Salesforce
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.
 

The Promised Land (in Angular)

  • 2. http://domenic.me https://github.com/domenic https://npmjs.org/~domenic http://slideshare.net/domenicdenicola THINGS I’M DOING  The Promises/A+ and ES6 promise specs  Working on Q  The Extensible Web Manifesto Domenic Denicola
  • 3. Angular is enlightened • Like most other client-side frameworks these days, Angular uses promises for everything async: • $timeout • $http + response interceptors • $resource • $routeProvider.when • Its built-in promise library, $q, is pretty good. • But first, let’s take a step back and start from the beginning.
  • 5. Web programming is async • I/O (like XMLHttpRequest, IndexedDB, or waiting for the user to click) takes time • We have only a single thread • We don’t want to freeze the tab while we do I/O • So we tell the browser: • Go do your I/O • When you’re done, run this code • In the meantime, let’s move on to some other code
  • 6. Async with callbacks // Ask for permission to show notifications Notification.requestPermission(function (result) { // When the user clicks yes or no, this code runs. if (result === 'denied') { console.log('user clicked no'); } else { console.log('permission granted!'); } }); // But in the meantime, this code continues to run. console.log("Waiting for the user...");
  • 7. Async with events var request = indexedDB.open("myDatabase"); request.onsuccess = function () { console.log('opened!'); }; request.onerror = function () { console.log('failed'); }; console.log("This code runs before either of those");
  • 8. Async with WTFBBQ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (this.readyState === this.DONE) { if (this.status === 200) { console.log("got the data!" + this.responseText); } else { console.log("an error happened!"); } } }; xhr.open("GET", "somefile.json"); xhr.send();
  • 9. These APIs 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. • 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.
  • 10. Instead of calling a passed callback, return a promise: var promiseForTemplate = $http.get("template.html"); promiseForTemplate.then( function (template) { // use template }, function (err) { // couldn’t get the template }); Promises are the right abstraction
  • 11. function getPromiseFor5() { var d = $q.defer(); d.resolve(5); return d.promise; } getPromiseFor5().then(function (v) { console.log('this will be 5: ' + v); }); Creating a promise
  • 12. function getPromiseFor5After1Second() { var d = $q.defer(); setTimeout(function () { d.resolve(5); }, 1000); return d.promise; } getPromiseFor5After1Second().then(function (v) { // this code only gets run after one second console.log('this will be 5: ' + v); }); Creating a promise (more advanced)
  • 13. 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. Promise guarantees
  • 14. 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. Promises can be chained
  • 15. var result; try { result = process(getInput()); } catch (ex) { result = handleError(ex); } var resultPromise = getInputPromise() .then(processAsync) .then(undefined, handleErrorAsync); The sync ⇔ async parallel
  • 16. var result; try { result = process(getInput()); } catch (ex) { result = handleError(ex); } var resultPromise = getInputPromise() .then(processAsync) .catch(handleErrorAsync); The sync ⇔ async parallel
  • 17. Case 1: simple functional transform var user = getUser(); var userName = user.name; // becomes var userNamePromise = getUser().then(function (user) { return user.name; });
  • 18. 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; });
  • 19. Case 3: handling an exception try { updateUser(data); } catch (ex) { console.log("There was an error:", ex); } // becomes var updatePromise = updateUser(data).catch(function (ex) { console.log("There was an error:", ex); });
  • 20. Case 4: rethrowing an exception try { updateUser(data); } catch (ex) { throw new Error("Updating user failed. Details: " + ex.message); } // becomes var updatePromise = updateUser(data).catch(function (ex) { throw new Error("Updating user failed. Details: " + ex.message); });
  • 21. var name = promptForNewUserName(userId); updateUser({ id: userId, name: name }); refreshUI(); // becomes promptForNewUserName(userId) .then(function (name) { return updateUser({ id: userId, name: name }); }) .then(refreshUI); Bonus async case: waiting
  • 22. Key features In practice, here are some key capabilities promises give you: • They are guaranteed to always be async. • They provide an asynchronous analog of exception propagation. • Because they are first-class objects, you can combine them easily and powerfully. • They allow easy creation of reusable abstractions.
  • 23. Always async function getUser(userName, onSuccess, onError) { if (cache.has(userName)) { onSuccess(cache.get(userName)); } else { $.ajax("/user?" + userName, { success: onSuccess, error: onError }); } }
  • 24. Always async console.log("1"); getUser("ddenicola", function (user) { console.log(user.firstName); }); console.log("2"); // 1, 2, Domenic
  • 25. Always async console.log("1"); getUser("ddenicola", function (user) { console.log(user.firstName); }); console.log("2"); // 1, Domenic, 2
  • 26. Always async function getUser(userName) { if (cache.has(userName)) { return $q.when(cache.get(userName)); } else { return $http.get("/user?" + userName); } }
  • 27. Always async console.log("1"); getUser("ddenicola“).then(function (user) { console.log(user.firstName); }); console.log("2"); // 1, 2, Domenic (every time!)
  • 28. getUser("Domenic", function (user) { getBestFriend(user, function (friend) { ui.showBestFriend(friend); }); }); Async “exception propagation”
  • 29. 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, function (err, friend) { if (err) { ui.error(err); } }); } }); } }); Async “exception propagation”
  • 31. Because promises are first-class objects, you can build simple operations on them instead of tying callbacks together: // Fulfills with an array of results when both fulfill, or rejects if either reject all([getUserData(), getCompanyData()]); // Fulfills with single result as soon as either fulfills, or rejects if both reject any([storeDataOnServer1(), storeDataOnServer2()]); // If writeFile accepts promises as arguments, and readFile returns one: writeFile("dest.txt", readFile("source.txt")); Promises as first-class objects
  • 32. Building promise abstractions function timer(promise, ms) { var deferred = $q.defer(); promise.then(deferred.resolve, deferred.reject); setTimeout(function () { deferred.reject(new Error("oops timed out")); }, ms); return deferred.promise; } function httpGetWithTimer(url, ms) { return timer($http.get(url), ms); }
  • 33. Building promise abstractions function retry(operation, maxTimes) { return operation().catch(function (reason) { if (maxTimes === 0) { throw reason; } return retry(operation, maxTimes - 1); }); } function httpGetWithRetry(url, maxTimes) { return retry(function () { return $http.get(url); }, maxTimes); }
  • 36. function MyController($scope) { $scope.text = "loading"; $scope.doThing = function () { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (this.readyState === this.DONE && this.status === 200) { $scope.text = this.responseText; } }; xhr.open("GET", "somefile.json"); xhr.send(); }; } // Doesn’t work, because the callback function is outside the digest cycle!
  • 37. function MyController($scope) { $scope.text = "loading"; $scope.doThing = function () { jQuery.get("somefile.json").then(function (responseText) { $scope.text = responseText; }); }; } // Still doesn't work: same problem
  • 38. function MyController($scope) { $scope.text = "loading"; $scope.doThing = function () { jQuery.get("somefile.json").then(function (responseText) { $scope.apply(function () { $scope.text = responseText; }); }); }; } // Works, but WTF
  • 39. function MyController($scope, $http) { $scope.text = "loading"; $scope.doThing = function () { $http.get("somefile.json").then(function (response) { $scope.text = response.data; }); }; } // Works! Angular’s promises are integrated into the digest cycle
  • 40. Useful things • $q.all([promise1, promise2, promise3]).then(function (threeElements) { … }); • $q.all({ a: promiseA, b: promise }).then(function (twoProperties) { … }); • Progress callbacks: • deferred.notify(value) • promise.then(undefined, undefined, onProgress) • But, use sparingly, and be careful • $q.when(otherThenable), e.g. for jQuery “promises” • promise.finally(function () { // happens on either success or failure });
  • 41. Gotchas • Issue 7992: catching thrown errors causes them to be logged anyway • Writing reusable libraries that vend $q promises is hard • $q is coupled to Angular’s dependency injection framework • You have to create an Angular module, which has limited audience • Angular promises are not as full-featured as other libraries: • Check out Q or Bluebird • But to get the digest-cycle magic, you need qPromise.finally($scope.apply). • Deferreds are kind of lame compared to the ES6 Promise constructor. • Progress callbacks are problematic.

Editor's Notes

  1. First benefit: separating outputs from inputs.
  2. First benefit: separating outputs from inputs.
  3. - Consistency gains: never call back with more than one fulfillment value or rejection reason.
  4. Just like a series of imperative statements. NB: “resolved” does not mean what many people think it means
  5. Pop quiz: what would happen if I consolidated the last two lines?
  6. Angular has $q.all(); the others are more just to illustrate.
  7. This is actually a cool example because it will work with any Promises/A+ library.