https://twitter.com/#!/trevorburnham
Wrote a blog on promises in jQuery
http://net.tutsplus.com/tutorials/javascript-ajax/wrangle-async-tasks-with-jquery-promises/
And has a Kickstarter project to fund a book on async programming
http://www.kickstarter.com/projects/869786663/async-javascript-book
It seems that my early mistake of confusing "resolved" and "fulfilled"
has become widespread. It is enshrined in the jQuery promise
implementation now. Thankfully, jQuery’s isResolved is deprecated.
http://api.jquery.com/deferred.state/
http://api.jquery.com/category/deferred-object/
For the record:
A deferred has two states:
- "pending"
- "resolved"
The resolution is (or becomes) another promise internally! All of the
"then" calls (and all other messages) that were called on this
deferred promise get forwarded to the next promise.
There are three kinds of promises:
- "fulfilled"
- "rejected"
- "deferred"
If you call deferred.resolve with a non-promise value, it gets
converted to a fulfilled promise internally. In that case, "resolve"
means "fulfill".
Here’s an over-simplified implementation of each type of promise:
function fulfilled(value) {
return {
then: function (callback, errback) {
var next = Q.defer();
next.resolve(callback(value));
return next.promise;
}
}
}
function rejected(error) {
return {
then: function (callback, errback) {
var next = Q.defer();
next.resolve(errback(error));
return next.promise;
}
}
}
function defer() {
var pending = [];
var next;
return {
promise: {
then: function (callback, errback) {
if (pending) {
pending.push([callback, errback]);
} else {
next.then(callback, errback);
}
}
},
resolve: function (value) {
if (value != null && value.then != null) {
next = value;
} else {
next = fulfilled(value);
}
pending.forEach(function (args) {
nextTick(function () {
next.then.apply(next, args);
});
})
pending = null;
}
}
}
Kris Kowal
This is confusing to me. I read "three kinds" as "three types". Thus
"it gets converted to a fulfilled promise internally" makes no sense.
So are there "three types of promises" or did you mean "A promise has
three possible states"?
jjb
I definitely wanted to avoid using the term "type". There is certainly
only one promise "interface". There are three implementations of that
interface in Q, but that is an implementation detail. The three
"kinds" of promises could certainly be implemented with a single
"type" that has three states. That is not really important though.
The point is that *conceptually*, a deferred promise can only be
"pending", "fulfilled", or "rejected". If you "resolve" a promise, it
might still be in any of those states, and it is certainly not a
synonym with "fulfilled", which is what the jQuery implementation
implies. For example, the deferred could still be "pending" if you
resolve it with another deferred promise (to do more work). This
happens implicitly every time you chain "then" calls.
Kris Kowal
> Having a then() that doesn't pipeline baffles me. What's the point?
There's some hope, at least:
This point is subtle, and comes from the non-obvious fact that you can resolve deferreds with promises. Intuitively I have in the back of my head a picture much like the incorrect one in jQuery: both deferreds and promises have exactly three states, pending/resolved|fulfilled/rejected|broken. And manipulating `deferred` directly manipulates `deferred.promise`.
It might be worth coming up with a newbie-friendly way of explaining this, for the wiki or perhaps the tutorial. I think a key ingredient is explaining exactly what the deferred methods do, and what happens if you call them with promises vs. with non-promise values.
I almost feel that everything would become clearer if deferreds got a `fulfill` method that *didn't* accept promises. (Or rather, if it got a promise, it passed it through without waiting for it to become fulfilled.) Then the majority of my code would switch to using `fulfill` for great clarity, and in the rare cases I want to resolve the deferred with a promise I would use `resolve`.
Hmm :-/.
Joe
http://bugs.jquery.com/ticket/11010
===============================================================================
Please access the attached hyperlink for an important electronic communications disclaimer:
http://www.credit-suisse.com/legal/en/disclaimer_email_ib.html
===============================================================================
I’ll look for some help on this. Thanks for blowing the whistle.
Kris Kowal
Joe
-----Original Message-----
From: q-con...@googlegroups.com [mailto:q-con...@googlegroups.com]
On Behalf Of Kris Kowal
Sent: Thursday, February 23, 2012 4:59 PM
To: q-con...@googlegroups.com
Subject: Re: [Q] Trevor Burnham on promises - and - The spread of my
mistake about resolved and fulfilled
Kris Kowal
Is this the kind of thing testling is supposed to solve?
("testling" almost got autocorrected to "testing". That would have been an embarrassing email.)
To solve the chaining issue in JQuery I had to use the 'pipe' method,
which seems to bridge the returned promise so that they can be chained.
Incidentally, JQuery doesn't have Q's 'all' method, instead it uses when
with an argument list. I had to invoke when using 'apply' to convert an
array to an argument list.
Joe
-----Original Message-----
From: q-con...@googlegroups.com [mailto:q-con...@googlegroups.com]
On Behalf Of Domenic Denicola
Sent: Thursday, February 23, 2012 5:08 PM
To: <q-con...@googlegroups.com>
Cc: q-con...@googlegroups.com
Subject: Re: [Q] Trevor Burnham on promises - and - The spread of my
mistake about resolved and fulfilled
===============================================================================