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.3k
2
Share
Common Patterns Using Promises
Neal Lindsay
January 07, 2016
More Decks by Neal Lindsay
See All by Neal Lindsay
Higher-Order Promises
neall
1
69
Promises are _Fun_damental
neall
0
61
Other Decks in Technology
See All in Technology
JEP 522 Deep Dive - G1 GC同期コスト削減によるスループット向上を徹底検証&解説
tabatad
1
540
脅威をエンジニアリングの糧にして:恐怖を乗り越えた先にあったもの / Turn threats into fuel for engineering: what lay beyond overcoming fear
nrslib
1
360
AI フレンドリーなエラー監視を TypeScript で実現する
shinyaigeek
2
200
『家族アルバム みてね』における インシデント対応との向き合い方 / Approach incident response in Family Album
kohbis
2
280
個人の発見を、組織の知恵に 〜生成AI活用を"探索"から"組織の仕組み"へ〜
kintotechdev
2
430
Generative UI × A2UI で AI エージェントを作った話 AI-DLC も使ってみた!
kmiya84377
1
300
TROCCOで始めるクラウドコストを民主化するためのFinOps
tk3fftk
2
520
形式手法特論:公平性制約の位相的特徴づけ #kernelvm / Kernel VM Study Kansai 12th
ytaka23
1
660
なぜハノーバーメッセに行くべきなのか 〜初参加だから語れること〜
tanakaseiya
0
190
電子辞書Brainをネットに繋げてみた(自力編)
raspython3
0
400
oracle-to-databricks-migration-with-llm-and-dbt
casek
1
390
Ruby::Boxでできること、Refinementsでできること
joker1007
2
300
Featured
See All Featured
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.1k
For a Future-Friendly Web
brad_frost
183
10k
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
130
Making Projects Easy
brettharned
120
6.7k
A Modern Web Designer's Workflow
chriscoyier
698
190k
The Cult of Friendly URLs
andyhume
79
6.9k
Docker and Python
trallard
47
3.9k
Writing Fast Ruby
sferik
630
63k
Music & Morning Musume
bryan
47
7.2k
How to Think Like a Performance Engineer
csswizardry
28
2.6k
Raft: Consensus for Rubyists
vanstee
141
7.5k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
710
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?