Promises for dummies
-
I'm doing a Microsoft training course on HTML/JS/CSS development, and it's touched on promises.
I'm having the exact same problem as every time I try to learn about promises, where it seems like every tutorial, no matter how "beginner", seems to assume some knowledge I don't have. Either that or I just have a huge mental block over whatever something that's too obvious to mention.
The training video recommended http://codefoster.com/usingpromises/ for more information. It's mostly the same as what was in the video and again I'm lost.
Representative sample:
In Windows 8 JavaScript development we have the WinJS.Promise. You create it like this…
new WinJS.Promise(function(c,e,p) { //function body });
The c, e, and p are parameters that are themselves functions. Within the function body, then, I can actually call c() when I want to complete the promise, call e() when I want to report an errant case, or call p() when I want to report progress.
Study this method I wrote that makes sure a file exists and if it doesn’t then it creates it…
function assureFileAsync() { return new WinJS.Promise(function (c, e, p) { if (fileExists("applicationData.json")) c(); else appdata.roamingFolder.createFileAsync("applicationData.json") .then(function (file) { return Windows.Storage.FileIO.writeTextAsync( file, JSON.stringify(starterData) ); }) .done(function () { c(); }); }); }
So
c
,e
andp
are functions. Fine. Do I define them? Do I have to pass them in when I call the promise? How does the progress one report progress? Does it take a numeric argument for percentage complete or something? None of this seems to be explained. Maybe a lot of this is specific to the WinJS version of promises? I don't knowIs there any guide out there that actually explains this stuff rather than saying you need error and progress functions then not mentioning them again?
-
@Jaloopa Looks like bad parameter names to me.
c
is probably the completed callback,p
is probably a progress callback, ande
is probably an error callback. I've never used WinJS before.
-
I don't know about a guide, but I'm more than willing to walk you through Promise usage.
I sent you a PM.
Filed under: IM, PM, DM... What are the kids calling them these days?
-
@Jaloopa said in Promises for dummies:
So c,e and p are functions.
they're also parameters. you're good to not define them.
the "standard" names for the parameters in javascript when you're not being a prick and using single letter symbol names are:
resolve
,reject
, andprogress
you should not rely on
progress
being defined in general, that's not part of the Promises/A+ spec. WinJS uses it but other promise libraries might not.you will call
resolve()
once when you successfully complete the promise, if you are providing a "return value" you may pass it as a single value asresolve(value)
if you need to provide multiple values to the promise chain you must use an array or object to contain them.you will call
reject(err)
once when you unsuccessfully complete the promise. You should provide a single parameter to the function call of typeError
the signature and usage of
progress()
is non standard and will vary from promise library to promise library, if it is supported at all. In general you call this function as often as you please to report progress through the promise. the parameters are generally, but not always, defined by the programmer to be whatever they find useful to report.
-
@error said in Promises for dummies:
I don't know about a guide,
I take it back, here is the article that introduced me to the concept.
-
Someone should really make a site that's a cross of jsfiddle, google docs, and a simple chat client.
-
@accalia said in Promises for dummies:
the "standard" names for the parameters in javascript when you're not being a prick and using single letter symbol names are: resolve, reject, and progress
Yeah, he does explain that it's
complete
,error
andprogress
, just no real context as to what they are and what you do with them@accalia said in Promises for dummies:
you will call resolve() once when you successfully complete the promise, if you are providing a "return value" you may pass it as a single value as resolve(value) if you need to provide multiple values to the promise chain you must use an array or object to contain them.
So if I'm using a promise from some library I need to know what sort of object would be returned by the promise in order to be able to call methods or access properties? Is it effectively what gets called when I do a
.then
on the promise?@error said in Promises for dummies:
I take it back, here is the article that introduced me to the concept.
Cool, I'll have a read of that
-
@error said in Promises for dummies:
Someone should really make a site that's a cross of jsfiddle, google docs, and a simple chat client.
-
@Jaloopa said in Promises for dummies:
So if I'm using a promise from some library I need to know what sort of object would be returned by the promise in order to be able to call methods or access properties? Is it effectively what gets called when I do a .then on the promise?
yeah. calling
.then(onResolve)
on a promise says "when the promise resolves call this function and pass the resolved value as the first (and only) parameter. if youronResolve
function returns a non-promise value it will be promoted to a promise and returned from thethen(onResolve)
call so you can continue chaining promises together. If youronResolve
returns a promise then the promise is returned instead, also allowing for more chaining.you can also call
then(undefined, onReject)
or.catch(onReject)
to register a rejection handler into the chain to do cleanup or fallback behavior.onReject()
has the same semantics asonResolve
you can also call
.then(onResolve, onReject)
to register both handlers to a single point in the promise chain, only one ofonResolve
oronReject
will be called depending on how the prior promise completes.
-
@accalia said in Promises for dummies:
you will call...
And I presume you should really write them as:
return resolve(); return reject(err);
So that no processing happens later on (eventually control will come back to your function otherwise. I've been bitten by that in other asynchronous js code.
-
@boomzilla said in Promises for dummies:
@accalia said in Promises for dummies:
you will call...
And I presume you should really write them as:
return resolve(); return reject(err);
So that no processing happens later on (eventually control will come back to your function otherwise. I've been bitten by that in other asynchronous js code.
this is correct.
you don't have to return the resolve/reject call (the functions return undefined) but it's considered a bad habit not to.
-
@Polygeekery said in Promises for dummies:
@error said in Promises for dummies:
Someone should really make a site that's a cross of jsfiddle, google docs, and a simple chat client.
props to cloud9
99.6% of sockbot was and is developed ther
-
@accalia said in Promises for dummies:
you don't have to return the resolve/reject call (the functions return undefined) but it's considered a bad habit not to.
Yeah, I've gotten lazy sometimes when it's at the "end" and resuming control would implicitly return right at the end, but I've also gotten lazy and created errors that to my mind are similar to not using braces for your
if
statements.
-
@Jaloopa said in Promises for dummies:
if I'm using a promise from some library I need to know what sort of object would be returned by the promise
A promise can return absolutely anything a function can. Similar to CPS, it will "return" the value by calling a callback. The only real difference is instead of calling
doSomething(foo, bar, function (result) { //do something with result })
You write it
doSomething(foo, bar).then(function(result) { });
Which makes for a much flatter call stack:
doSomething(foo, bar).then(function(result) { return doSomethingElse(result); }).then(function(secondResult) { //something });
instead of CPS:
doSomething(foo, bar, function (result) { doSomethingElse(result, function(secondResult) { //something }); });
A promise is a wrapper around a function. Therefore, when you construct one, you hand it a function.
The promise chain will halt execution if an error result is returned. Therefore, it needs to know when you've reached an error state you cannot recover from. Therefore, you are handed two functions to work with: one to return a value on success, and one to signal an error state. Your library apparently uses a third, but I don't usually work with that.
-
@accalia said in Promises for dummies:
.catch(onReject)
Stupid browsers have issues with method names that are keywords.
I've had to write
promise[ 'catch' ](...)
, but prefer.then( null, function() {} )
-
@Polygeekery said in Promises for dummies:
@error said in Promises for dummies:
Someone should really make a site that's a cross of jsfiddle, google docs, and a simple chat client.
have I been doing with my life?
-
@error said in Promises for dummies:
@Polygeekery said in Promises for dummies:
@error said in Promises for dummies:
Someone should really make a site that's a cross of jsfiddle, google docs, and a simple chat client.
have I been doing with my life?
They want my for a free account.
-
@accalia said in Promises for dummies:
the "standard" names for the parameters in javascript when you're not being a prick and using single letter symbol names are: resolve, reject, and progress
Are you sure? Those names suck. I'd rather use
success
andfailure
.
-
@pydsigner
Those names only make sense ifsuccess
indicates that you torpedoed the user's request and thatfailure
means you weren't able to find any way to prevent it.
-
@pydsigner said in Promises for dummies:
@accalia said in Promises for dummies:
the "standard" names for the parameters in javascript when you're not being a prick and using single letter symbol names are: resolve, reject, and progress
Are you sure? Those names suck. I'd rather use
success
andfailure
.yes, i am sure.
however it is JS hence the scarequotes.
-
@pydsigner said in Promises for dummies:
@accalia said in Promises for dummies:
the "standard" names for the parameters in javascript when you're not being a prick and using single letter symbol names are: resolve, reject, and progress
Are you sure? Those names suck. I'd rather use
success
andfailure
.Those terms may create a false implication for certain usages of the API.
d
-
@boomzilla said in Promises for dummies:
Yeah, I've gotten lazy sometimes when it's at the "end" and resuming control would implicitly return right at the end, but I've also gotten lazy and created errors that to my mind are similar to not using braces for your
if
statements.Given that "lazy" is the operative word when it comes to promises, that seems appropriate.
I've seen some absurd ways of implementing a continuation before, but seriously, Microsoft?
Oh, wait, Microsoft didn't come up with this shitshow, they just implemented it. Good on them, I guess.
-
@izzion said in Promises for dummies:
@pydsigner
Those names only make sense ifsuccess
indicates that you torpedoed the user's request and thatfailure
means you weren't able to find any way to prevent it.I think I'm :woosh:ing right now.
-
I basically proposed defining true as false and false as true. I just left off the from the end of my statement :p
Also, dammit emoji autocomplete, I do not want to ship a every time I stick my tongue out.
-
@izzion said in Promises for dummies:
I basically proposed defining true as false and false as true.
VB uses 0 for
False
and -1 forTrue
Spoiler
It's because it treats operators as bitwise, not logical. So `True` is `Not False`, which is `~0`, which is `11111111111111111111111111111111`, which is -1.INB4 VB is not logical.
Filed under: Yet another Markdown
-
@ScholRLEA said in Promises for dummies:
Given that "lazy" is the operative word when it comes to promises, that seems appropriate.
It all feels like a rather nasty poor-man's coroutine to me, with all the complexity of needing to do non-trivial closure management and so on, but a much more complicated syntax. (Coroutines themselves can be a lot like lightweight threads, depending on just how much stack is preserved…)
-
@dkf I didn't see that aspect of it earlier, but that's actually a good point, especially given the way the
progress
callout seems to work. It isn't quite a co-routine system as it is, but I can see how you could use it as one... if you wanted to... and had no better way to do it.It also has some feel of Python-style generators, in that you could see it as having the
progress
callout for the 'real' program and the functor that 'is' the promise as a data source or data sink that can be repeatedlycalledreturned to as an interrupted closure, but surely there would be better ways to do that even in vanilla Javascript (though that would fit the lazy evaluation model after a fashion). The co-routine use case, as ludicrous as it is, makes more sense than using it for that.In any case, my impression is that the main use case it is intended for is, as I said earlier, to create a thunk to a continuation for the purposes of lazy or delayed evaluation, which is sort of the idea implicit in the name 'promise'.
The real problem I have with it is that it's a camel - not quite lazy evaluation, not quite a generator, not quite a co-routine, and not quite a quaject, any one of which could be implemented with little trouble in Javascript, I think, though generators wouldn't have the language support they have in Python). It is a generalization that doesn't really unify the ideas, and complicates the models rather than simplifying them.