Promises

Claus Reinke claus.reinke at talk21.com
Fri Nov 9 09:06:54 PST 2012


> Both then and fail return another promise for the result of the callback
> 
>     var someData1P = query(q1);
>     var processedDataP = someData1P.then(function first(data){
>         return process(data); // if what's returned here is a promise 
> P, then
>         // processedDataP will be a promise for the resolution value of 
> P, not
>         // a promise for a promise of the resolution value of P
>         // Said another way, in a .then callback, the argument is 
> always a non-promise value
>     });

Perhaps I'm misunderstanding - my reading of the spec (fairly
concise tutorial at https://github.com/kriskowal/q) is: 

- originally, 'then's success callback returned values only, which 
    were wrapped into a promise by 'then'; 

- nowadays, 'then's success callback may also return a promise,
    which will *become* the result of 'then';

the latter option gives the type -if I read '.then' as a binary op
and focus on the success callback only-

    then : Promise(val) => (val => Promise(val2)) => Promise(val2)

which is familiar from monadic programming.

If I read this correctly, you could pass a promise to the next 'then'
callback by returning a promise that resolves to a promise (val2 
would itself be a promise;-).
 
> The fact that the .then of the next promise is called when the previous 
> normally returned and the .fail when the previous threw makes me feel 
> like promise chains have sort of two parallel channels to which one 
> decides to branch to by returning or throwing.

Yes, and that makes me a bit uneasy. The alternative style, with
only success callback for 'then' and only failure callback for 'fail'
makes more sense to me. It makes both error handling and error
passing more explicit - fail is the async catch.

One example of why mixing both callbacks into 'then' is misleading: 
the q-tutorial gives two examples of chaining styles, nested and flat. 

Refactoring flat chains into nested ones can be necessary when
access to multiple promise results is needed. That refactoring fails
if 'then's are used for failure callbacks, and using 'fail' would make
that more obvious.
 
> # Debugging
> It's been said in other messages, one part where Q promises fell short 
> was debugging. With thrown errors, if you uncatch one, your 
> devtools/console will tell you. To my experience, with the Q library, if 
> you forget a .fail, an error may end up being forgotten which is bad 
> news in development mode (and I've wasted a lot of times not knowing an 
> error had happened and chasing this errors after understanding that's 
> why "nothing" was happening). I'm hopeful built-in promises will be able 
> to compensate.

Tooling for asynchronous programming is interesting in general.

As a minor helper: some debuggers allow to stop at any raised exception,
so you could see where it gets transformed into a failed promise. Another
idea: log such transformed errors, or automate matching of handled
failed promises against generated failed promises.
 
There is also the interesting issue of asynch coding constructing code
that will raise errors where the original error handlers wrapping the
code construction site aren't in place anymore.

Claus
 


More information about the es-discuss mailing list