New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Propagate progress. Fixes #113. #114
Conversation
Alright, I’ll entertain it as an experiment. It does have the theoretical flaw that progress through a conjunction is not necessarily bound by the progress of a single operand, but you can work around that case explicitly. Consider this case: var A = fast();
var B = slow();
var C = Q.when(A, function () {
return B;
}); I’m curious how that plays out. I’m guessing that you get a journey to 100%, then a drop to whatever the progress on B is at that moment, and a slow progression back up to 100%. That, or you go quickly to 100% and stall. I would have to experiment, but I’m presently working on something else. |
Oh interesting, I hadn't considered that case. Yeah we don't (and shouldn't) to any forwarding for |
Here's a demo of that: It looks like it emits progress from |
Next step is to see what the other progress-using promise libraries (jQuery, When, WinJS) do.
|
Thanks for the legwork. The jsfiddle is insightful. |
This is proving to be quite a complex issue. I'd almost be inclined to require users to be explicit about what progress gets forwarded and how it gets forwarded. |
I'm planning to add progress propagation to Dojo 1.8.1. If the progback returns a non-undefined value, that value is emitted as a progress update on the returned promise. |
The problem with this approach, I would think, is that it doesn't address my first example in #113. Namely, the following works: promiseWithProgress
.progress(console.log)
.finally(function () { })
.end(); whereas the following does not: promiseWithProgress
.finally(function () { })
.progress(console.log)
.end(); This seems counterintuitive to me and makes using the shortcut functions ( |
I like the idea of translating the progress in the progback. It would also follow that progress is a single value, so we should need to lock down the arity of the progress emitter. It is probably okay, for the purpose of progress notifications, to assume that the operation will not fail, and to reset the progress to the resolution of the handler. It is probably also okay to assume that a finally clause will not cause further delay (though this is not a guarantee). Maybe it is okay for progress to pass-through by default, and to be able to adapt the progress in the progback. We would probably also need ways to compose progress values from other promises in the progback, perhaps analogously to how we compose promises in callbacks and errbacks. Perhaps progress values need to be promises themselves so we can use the same composition techniques. var A = chicagoToBoston();
var B = bostonToChicago();
var C = Q.progress(A, function (aProgress) {
return Q.progress(B, function (bProgress) {
return // ?
});
}); |
IIRC deferreds only have single resolution, rejection or progress values.
Does that assumption mean there is no rejection of the promise if the operation does fail? I don't think that's right.
In Dojo the progress is pass-through if there is no progback registered. |
If you recall what correctly? Promises/A gives no guidance. On the other hand all libraries but jQuery do have single progress values (and jQuery doesn't count, they don't even have single fulfillment values or rejection reasons). More discussion on Q Continuum.
This makes sense, but I'm not sure I gather the exact semantics of the transformation. How does this behave? promise.then(null, null, function (x) {
return Q.delay(1000).then(function () { return x + 10; });
})
.then(f, r, p); Does |
Ha, fair enough. Single values all the way for me. I'm not familiar with the var dfd = new Deferred();
dfd.then(f, r, p);
dfd.progress("foo"); // --> p("foo")
dfd.progress(otherPromise); // --> p(otherPromise)
dfd.resolve("bar"); // --> f("bar");
dfd.progress("baz"); // noop |
Sorry, I agree that notifying a deferred of progress ( |
The promise is passed on as a progress update. I don't think progress is used often enough to warrant much sugar. In Dojo for instance there is no sugar for For the scenario you're describing: var otherPromise = promise.progress(function(update){
// Process the update asynchronously, return a promise to propagate more progress later…
return asyncPromise;
}); Without magic handling of the progress promise you can still achieve the same by manually forwarding the promise state: var otherDeferred = new Deferred(promise.cancel);
promise.then(otherDeferred.resolve, otherDeferred.reject, function(update){
asyncPromise.then(null, null, otherDeferred.progress);
});
var otherPromise = otherDeferred.promise; |
Superceded by #125. |
If we think this is a good idea, let's merge it; it certainly makes my stuff easier.