Promises

Mariusz Nowak medikoo+mozilla.org at medikoo.com
Thu Nov 8 03:45:48 PST 2012



Kevin Smith-21 wrote:
> 
> The only hard part that isn't really addressed by currently library
> implementations is error handling.  I feel pretty strongly that rejections
> (and by extension, errors thrown from `then` callbacks), should ALWAYS be
> observable.  In other words, if a rejection is not observable via error
> listeners at the time when error listeners should be called, then an
> unhandled error should be thrown by the runtime.
> 
> In my usage of promises I have never wanted anything other than this
> behavior.
> 
> 

I think source of a problem is that we center usage of promises just around
'then' function, when 'then' is about two things:
1. Provides us with resolved value
2. Extends promise chain with another promise.

What's important, in many use cases we're not after point 2, we don't need
extended promise, and it's promise extension fact that, makes our errors
silent when we don't expect them to be.

It's difficult to naturally expose errors when the only way to add observers
is `then`. Technically to do it we need to always write error handler as
below:

promise.then(function () {
  // process the value;
}).then(null, function (err) {
  // Need to get out of promise chain with setImmediate (or nextTick if in
Node.js)
  setImmediate(function (function () {
    throw err; // Finally error will be thrown naturally;
  });
});

This one of the reasons for which some developers preferred to stay away
from promises, and I totally I agree with them.

Q implementors spotted that issue, and provided `done` (initially named as
`end`) function. Which helps to work with that issue:

promise.then(function () {
 // process the value
}).done(); // Sugar for above

Still in Q (as far I as know) we're not able to get to resolved value
without extending the promise chain and that's not great.

Final conclusion is that there needs to be a way to observe resolved value
on promise without extending the chain as `then` does.

And yes there is library that does that. In deferred implementation
(https://github.com/medikoo/deferred ) I've solved it by providing two other
functions that have same signature as 'then' but *don't extend* promise
chain:

promise.end(onFulfilled, onRejected); // returns undefined
If onRejected is not provided then failed promise will throw, additionally
any errors that may occur in provided callbacks are thrown natural way
(they're not caught by promise implementation)

promise.aside(onFulfilled, onRejected); // returns self promise
This actually works similar to functions found in jQuery's Deferred. It's
useful when we want to return same promise, but on a side, work with
resolved value. If onRejected is not provided nothing happens (as we return
promise for further processing), but any errors that occur in callbacks are
thrown natural way  (they're not caught by promise implementation)

With such design your function of choice in first place should always be
'end', in that case there is no problem with silent errors. `then` should be
used *only* if you have a reason to extend the chain, and pass result
elsewhere.


-----
Mariusz Nowak

https://github.com/medikoo
-- 
View this message in context: http://old.nabble.com/Promises-tp34648686p34655893.html
Sent from the Mozilla - ECMAScript 4 discussion mailing list archive at Nabble.com.



More information about the es-discuss mailing list