SlideShare a Scribd company logo
1 of 42
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

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
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
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
 
"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
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
"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
 
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
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
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
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 

Recently uploaded (20)

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
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
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
 
"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
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
"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
 
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
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
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
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 

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.