Hey Bob, thanks for the thoughts. A few comments inline.
On Saturday, June 29, 2013 6:08:01 PM UTC-4, Bob Myers wrote:
I'd suggest, for no particularly good reason other than it seems useful, that promises be accepted as progress values.The progress update is posted (ie the progress handler is called) when the promise fulfills.
The progress handler may also return a promise; if it does, downstream promises are given progress alerts when that promise fulfills.
Progress propagation stops when the progress handler throws, but if the progress handler was a promise its error handler can be invoked to deal with that.
Actually, this is a problem. Promises/A+ states that promise handlers may be called at most once. So, if we call a rejection handler in response to a progress error, I can see only 3 choices:
- call the associated rejection handler (assuming you meant the one that was passed to the same then() as the progress handler which triggered the progress error): this means we can never call this rejection handler again, which is bad since we need to call it if the promise rejects. Calling a rejection handler before a promise becomes rejected will also be disallowed by the upcoming Promises/A+ v1.1, which leads to ...
- transition the promise to the rejected state *and also* call the rejection handler: this leads to some tricky situations, but more importantly grants too much authority to a party who otherwise would not be able to reject the promise in question
- don't call the rejection handler: unfortunately, this puts us back at square one
It's a tricky situation for sure.
Allowing promises for progress event data also leads to some tricky situations. For example, should a progress update be able to postpone the resolution of a promise indefinitely? For example:
var d = when.defer();
consumer1(d.promise);
consumer2(d.promise);
function consumer1(promise) {
// consumer1 has too much authority, can prevent the promise
// from ever resolving
promise.notify(promiseThatIsPendingForever);
}
function consumer2(promise) {
// peer consumers of the same promise should never be able to
// interfere with one another via the promise
// consumer1 has prevented consumer2 from ever doing the important work
// even though consumer1 should not have that authority
promise.then(doImportantWork);
}
The sole responsibility for d.promise's state must belong to the owner of d.resolver, not with consumers of d.promise.
There are also weird (but probably less hazardous) cases like:
var d = when.defer();
d.notify(promiseThatFulfillsInTenSeconds);
d.resolve(promiseThatFulfillsInOneSecond);
When does d.promise fulfill?
Part of the problem is that progress events deal with the time before a promise resolves, and fulfillment/rejection handlers deal with the time afterward.
Any thoughts on those issues? I'm def interested in figuring out a good solution