[dojo-contributors] Promises

Eugene Lazutkin eugene at lazutkin.com
Thu Mar 4 20:57:06 EST 2010

Hash: SHA1

If it is 100% backwards compatible yet smaller --- I am all for it. But
setTimeout() hack bums me out. It is bad on so many levels including
debugging. And throwing an error from a setTimeout() callback... What is
the grand idea anyway? Who is going to catch it? How to catch it? Why
bother? How can it help me to find the source of an error? Why not
console.log() an error --- the effect looks similar? Why is this a good
way to do the default error processing?

Speaking about the (default) error processing.

1) The exception processing is not a symmetric thing. While try/catch
are symmetric, throw vs. try/catch are not. I think you make a mistake
by wrapping all three together and declaring that all three things
always go together. No, they are not. Usually there are many more things
that can throw exceptions than places to catch them. The same should be
applied to Deferreds/Promises.

2) OK, you caught an error. Now what? Not hypothetically but
realistically? Usually you have two major choices:

a) Retry an action, or rollback and retry a transaction --- 99% of cases
we are talking about (faulty) I/O, which can be treated this way. Try to
rollback and repeat "division by 0". :-)

b) Tell a user about the problem in some way.

Even (a) is frequently done by doing (b) --- asking user, if she wants
to repeat an action.

How is it done in the Real Life (tm)? You have to have an error
reporting facilities in your application. It can be something as simple
as using alert(), or (in reality) you have some visual design to present
all errors in a uniform way. Even in UI-less applications usually you
have a standardized logging or something to this effect.

Typically in my apps I have a top-level try-catch, which does exactly
what I described above. I rarely catch individual exceptions --- usually
splitting them in 2-3 classes (e.g., I/O vs. everything else) are enough
for me.

Now back to Deferreds/Promises. They don't change anything. But they
change an architecture a little bit. One way to do it is to have default
global callbacks, which are called when nobody else is handling an
error. If I want to be flexible, I use a stack of such callbacks ---
only the top one is called. I can push to stack and pop from stack my
custom error processors in different phases of my app to have some

I think it is a reasonable approach. I know from practice that it works.
And the technique doesn't rely on any hacks.

My proposal is to implement this default callback technique at the
library level instead of doing setTimeout() and throw exceptions from
nowhere. It doesn't require much code, yet flexible, practical, and
works as advertised. ;-)

Additionally, for debugging purposes, I think it would be nice to log an
error regardless if it was processed or not. From my experience I want
to know about it in 99% of the cases, while debugging. Make it a global
debugging switch, or reuse an existing one. In any case it is better
than to pepper all error callbacks with logging code.

Eugene Lazutkin

PS: Is it "tl;dr" case again? Just checking. :-D

On 03/03/2010 04:47 PM, James Burke wrote:
> On Wed, Mar 3, 2010 at 2:10 PM, Kris Zyp <kzyp at dojotoolkit.org> wrote:
>> I put together a backwards compatible variant of this implementation.
> This sounds promising. Ha, see what I did there? OK, that already
> sounds lame to me after just saying it.
> Anyway, I am keen to see this in a 1.5, even better if it meshes with
> the CommonJS Promises. However it seemed like the CommonJS version was
> still in flux? Kris, how do view the state of the process/progress
> over in CommonJS-land? Any possible implementation divergence between
> our code and theirs?
> I am also not so keen on a setTimeout for the error case. It means we
> need a setTimeout implementation for whatever environment runs the
> code, and for debugging, it loses the stack trace.
> I appreciate that it is a hard thing to sort out. Some
> Deferred/Promise use expect errors to just be eaten but other uses
> what to know about errors. The basic problem seems to be not knowing
> the error intention at the point of calling the reject/errback.
> With traditional Dojo use of Deferreds, it seemed almost reasonable to
> say if there was no errback listeners when the error is thrown we can
> just throw in that case.
> However, with a dojo.when(something, callback, errback) sort of
> approach, the errback listener is likely not be be bound until after
> the something's Deferred may have erred out? I'm thinking out loud a
> bit here, maybe Kris or Eugene have other suggestions on how to look
> at the problem.
> Making sure these things are easy to debug is a pretty big deal. After
> spending some time in Twisted land, and dealing with the current state
> of dojo.Deferred error debugging, tracking down errors effectively
> would make this sort of deferred/async logic a lot easier to get into.
> James
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/


More information about the dojo-contributors mailing list