Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Common Patterns Using Promises
Search
Neal Lindsay
January 07, 2016
Technology
2
2.3k
Common Patterns Using Promises
Neal Lindsay
January 07, 2016
Tweet
Share
More Decks by Neal Lindsay
See All by Neal Lindsay
Higher-Order Promises
neall
1
66
Promises are _Fun_damental
neall
0
60
Other Decks in Technology
See All in Technology
OpenCensusと歩んだ7年間
bgpat
0
320
AIの個性を理解し、指揮する
shoota
3
620
Data Engineering Guide 2025 #data_summit_findy by @Kazaneya_PR / 20251106
kazaneya
PRO
7
790
DMARCは導入したんだけど・・・現場のつぶやき 〜 BIMI?何それ美味しいの?
hirachan
1
110
ストレージエンジニアの仕事と、近年の計算機について / 第58回 情報科学若手の会
pfn
PRO
4
960
Amazon Q Developer CLIをClaude Codeから使うためのベストプラクティスを考えてみた
dar_kuma_san
0
320
書籍『実践 Apache Iceberg』の歩き方
ishikawa_satoru
0
450
プロダクト開発と社内データ活用での、BI×AIの現在地 / Data_Findy
sansan_randd
1
780
re:Inventに行くまでにやっておきたいこと
nagisa53
0
980
アノテーション作業書作成のGood Practice
cierpa0905
PRO
1
380
データエンジニアとして生存するために 〜界隈を盛り上げる「お祭り」が必要な理由〜 / data_summit_findy_Session_1
sansan_randd
1
880
組織全員で向き合うAI Readyなデータ利活用
gappy50
5
2.1k
Featured
See All Featured
Designing Experiences People Love
moore
142
24k
RailsConf 2023
tenderlove
30
1.3k
VelocityConf: Rendering Performance Case Studies
addyosmani
333
24k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
22k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
10
640
Navigating Team Friction
lara
190
15k
The Language of Interfaces
destraynor
162
25k
Git: the NoSQL Database
bkeepers
PRO
431
66k
Build your cross-platform service in a week with App Engine
jlugia
234
18k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
9.7k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
54k
Making the Leap to Tech Lead
cromwellryan
135
9.6k
Transcript
Common Patterns Using Promises
Neal Lindsay @neall
[email protected]
what is a promise? patterns anti-patterns stunning conclusion!
a container you get immediately for a value you get
eventually
promises are for asynchronous data
event handlers? streaming data? each “then” only happens once
2010 - promises/A 2011 - jQuery “deferreds” 2012 - promises/A+
2013 - browser promises
new Promise(function(resolve, reject) { if (thingsGoWell) { resolve('value'); } else
{ reject(Error('reason')); } });
Promise.resolve('value'); Promise.reject(Error('reason'));
p.then( function(value){…}, function(reason){…} );
don't call it a callback (it’s been here for years)
data handler error handler
.then() returns a new promise np = p.then(…);
p ≠ np (dumb math joke)
how does this new promise resolve?
1. falls through if no handler
p.then(f) p.then().then(f)
1. falls through if no handler 2. rejected with any
error thrown 3. resolved with a value returned 4. except… if a promise returned, “becomes” that promise
np = p.then(function(value) { return Promise.resolve(3 + value); });
patterns
chaining vs fanning
get('/dog') .then(JSON.parse) .then(function(dog) {…}); chaining
p = get('/dog').then(JSON.parse); p.then(alert); p.then(playFetch); fanning
cache = {}; getUserWithCache = function(id) { return cache[id] =
cache[id] || getUser(id); }; getUserWithCache(3).then(displayName); // later getUserWithCache(3).then(displayAge);
naming
value: plain old noun p.then(function(dog) {…});
p.then( undefined, function(error) {} ); error: error
p.then( undefined, function(error) {…} ); p.catch( function(error) {…} );
p.then( undefined, function(error) {…} ); p['catch']( function(error) {…} );
function that returns a promise: imperative verb phrase guessFavoriteColor() .then(function(color)
{…});
promise: past-tense verb phrase gotScruffy = getDog('scruffy'); gotScruffy .then(function(scruffy) {…});
name handler functions for readability
getDog('scruffy') .then(function(dog) { return getPerson(dog.ownerId); }) .then(function(person) { return person.name;
}) .then(alert);
getOwner = function(obj) { return getPerson(obj.ownerId); }; readName = function(obj)
{ return obj.name; }; getDog('scruffy') .then(getOwner) .then(readName) .then(alert);
use higher- order functions
multiplyBy = function(x) { return function(y) { return x *
y; }; }; timesThree = multiplyBy(3); alert(timesThree(2)); // 6
getOwner = function(obj) { return getPerson(obj.ownerId); }; readName = function(obj)
{ return obj.name; }; getDog('scruffy') .then(getOwner) .then(readName) .then(alert);
readProperty = function(propertyName) { return function(obj) { return obj[propertyName]; };
}; getDog('scruffy') .then(readProperty('ownerId')) .then(getPerson) .then(readProperty('name')) .then(alert);
recover from errors
getDog('scruffy') .then(alert);
var getDefaultDog = function() { return getDog('fluffy'); } getDog('scruffy') .catch(getDefaultDog)
.then(alert);
var getEmergencyDog = function() { return {name: 'claude'}; }; getDog('scruffy')
.catch(getDefaultDog) .catch(getEmergencyDog) .then(alert);
anti-patterns
returning data not in a promise
var getEmergencyDog = function() { return {name: 'claude'}; }; getDog('scruffy')
.catch(getDefaultDog) .catch(getEmergencyDog) .then(alert);
var getEmergencyDog = function() { return Promise.resolve({name: 'claude'}); }; getDog('scruffy')
.catch(getDefaultDog) .catch(getEmergencyDog) .then(alert);
unnecessary function wrapping
get('/dogs') .then(function(response) { return JSON.parse(response); }) .then(doSomething);
get('/dogs') .then(JSON.parse) .then(doSomething);
except…
getDog('scruffy') .then(window.alert); // works getDog('scruffy') .then(console.log); // TypeError!
getDog('scruffy') .then(function(dog) { console.log(dog) }); // works, but meh :-/
getDog('scruffy') .then(console.log.bind(console));
synchronous code after promise code
getDog('scruffy').then(alert); alert('Good dog!');
getDog('scruffy') .then(alert) .then(function() { alert('Good dog!'); });
inappropriately chaining queries
getDog('scruffy') .then(goWalkies);
can you walk my dog too?
getDog('scruffy') .then(goWalkies); getDog('fluffy') .then(goWalkies);
getDog('scruffy') .then(function (scruffy) { return new Promise(function(resolve) { getDog('fluffy') .then(function(fluffy)
{ resolve([scruffy, fluffy]); }); }); }) .then(goWalkies);
Promise .all([ getDog('scruffy'), getDog('fluffy'), getEmergencyDog() ]) .then(goWalkies);
Promise .all([ getDog('scruffy').then(getOwnerForDog), getDog('fluffy').then(getOwnerForDog), getEmergencyDog().then(getOwnerForDog) ]) .then(renegotiateWalkingRates);
conclusion
chain vs fan
naming
move inline functions into named variables
replace named functions with generated functions
return promises even for some static data for consistency
don't wrap functions for no reason
but do use function.bind() when needed
keep synchronous code above promise code
don't chain expensive queries when you can avoid it
thank you
questions?