returning undefined from a Deferred callback/errback

39 views
Skip to first unread message

Ivan Kozik

unread,
Dec 9, 2010, 12:28:24 AM12/9/10
to closure-lib...@googlegroups.com
This is a note for users of goog.async.Deferred. The implementation
of Deferred in Closure Library has an unusual property: returning
undefined (or not returning anything) from a callback or errback
passes the last value (*not* undefined) into the next
callback/errback. This matches the behavior of dojo's Deferred, but
is unlike any other implementation that I know of (incl. the Deferred
in Mochikit, Divmod/Nevow/js, and the original Deferred in Twisted.)
Re-using the last value automatically was definitely not intended as
part of the original Deferred design.

Because of this behavior, I usually need to include `return null` in
my errbacks. Also, this behavior leaves a reference to a (possibly
heavy-weight) object in the Deferred, which might cause a problem
somewhere.

I would love to do all of the work of removing the above behavior, but
I assume it's probably too late. I already have unit tests for the
"good" behavior. If anyone else cares about this, please let me know.


Thanks,

Ivan

Fredrik Blomqvist

unread,
Dec 9, 2010, 6:59:06 AM12/9/10
to Closure Library Discuss
This is an interesting case. I do understand your point, it is more
strict, but I'd like to advocate the other path.

Here's for example a very common pattern in real life code I'd say:
----------
d.addCallbacks(doSomething, logError);
---------
If no undefined piping, the above will stop possible further "real"
error handling.
My experience with people (myself included..) using the Deferred API
in MochiKit is that they don't expect code like the above to transform
an errback into a success-callback.
I think the overhead of having to do an explicit return to close an
errback is less than the overhead and risk of closing and hiding
errors by forgetting to pipe the input.

Initially I tried couple of helper methods that would simply wrap the
attached function in a pipe-through etc, but finally I decided, partly
based on Dojo and Closure lead, to patch MochiKit Async to propagate
values.
(See my MochiKit fork here: https://github.com/blq/mochikit/commit/577477c888c13394b9f893bcec90320e50b845a2#diff-0
)

Secondly, I think the case of keeping an error object reference is
more of a hypothetical issue. Very rarely have I seen any particularly
heavy objects being passed as errors. I.e it should not be a case
mandating optimization on the level of API or behavior changes (side
note: optimizations for callbacks/errbacks and heavy return values
should rather be some kind of lazy callback pattern for example).

Fundamentally though I guess it's a case of overlapping logic and use-
case for a single function, listening and _re_acting on the result of
an operation is different than intending to participate in the
handling and processing of the result.

Will be interesting to hear other opinions
// Fredrik Blomqvist

Peter Higgins

unread,
Dec 9, 2010, 8:25:00 AM12/9/10
to closure-lib...@googlegroups.com
FWIW, this behavior was recently changed in Dojo. Deferred remains
backwards compatible, where the return is passed along, barring
undefined, which shows the behavior you describe. But now everything is
a dojo.Promise internally, so both behaviors work.

It should be trivial to port the changes made to dojo.Deferred to closure.

http://bugs.dojotoolkit.org/ticket/11946

~phiggins

Peter Higgins

unread,
Dec 9, 2010, 8:26:04 AM12/9/10
to closure-lib...@googlegroups.com
Wrong link. :/
http://www.sitepen.com/blog/2010/05/03/robust-promises-with-dojo-deferred-1-5/

My apologies for the noise.

~phiggins


On 12/9/10 12:28 AM, Ivan Kozik wrote:

bolinfest

unread,
Dec 9, 2010, 12:57:54 PM12/9/10
to Closure Library Discuss
Independently, I got burned yesterday where I passed an object literal
to errback() and then the errback function I had registered got an
Error instead of my object literal. After taking a deeper look and
realizing this is the intended (albeit undocumented) behavior, I
finally carried out my plan to create an alternative implementation to
address that, as well as other issues with goog.async.Deferred.

I started a separate discussion where I propose a new implementation
named goog.deferred.Deferred: http://bolinfest.com/deferred/

The discussion is at: http://groups.google.com/group/closure-library-discuss/browse_thread/thread/1c0e2649d05ffbdf

On Dec 9, 8:26 am, Peter Higgins <phigg...@gmail.com> wrote:
> Wrong link. :/http://www.sitepen.com/blog/2010/05/03/robust-promises-with-dojo-defe...
Reply all
Reply to author
Forward
0 new messages