First, performance is rarely an issue when adding a callback to deferred. Also, current jQuery deferreds implementation is not performance oriented. I guess so, because there are faster ways to implement deferreds. There are faster deferred libraries. You could make the new .done/.fail/.then work faster, but I guess you just concentrated on 'good enough' performance and the nice jQuery-style API.
Performance is rarely an issue unless you have to create a new Deferred each time you add a *single* callback. Hence why
progress do not create a new Deferred internally.
jQuery Deferred have detachable methods. This makes the cost of creating a Deferred much heavier than prototype-based implementations (both in time AND memory). This is not something you can optimize away once you made all the methods attaching callbacks create a Deferred internally.
Second, about the API. Julian, I wrote a letter to you about 3 years ago when deferreds were introduced to jQuery explaining the same issue about .done/.fail/.then. You declined it then, but through years jQuery gradually follows this vector. You introduced .pipe as another method which does .then right. Now .then switched to .pipe as it should have been from the beginning.
This is not at all what the conversation was about. In particular, there was no mention of
fail. The only proposal there was for
pipe to handle exceptions like "In *all* implementation of deferreds" (quote).
I still stand by the arguments I gave you back then (and to which you promised an answer that never came). Pre-emptively catching exceptions and promoting them as rejections ignores the very meachanics of a promise and creates all sorts of problems which, to this day, the promise comunity hasn't found any decent solution to (though some like to claim otherwise).
Back to the conversation at hand, if you remember, we had just introduced
pipe as the async chaining utility because some in the project didn't want to break backward compatibility with the simplest
then we had at the time. We eventually decided to break backward compatibility by aliasing
then. The deciding point was that there was still a means to attach callbacks without the cost of creating a Deferred, namely
Not to mention that
progress allow for multiple callbacks to be added at once which an async chaining implementation would prohibit.
Please continue going the right way and finally fix .done/.fail.
There is no notion of right or wrong here. Different elements in an API will have different use.
progress are just as "right" as
then. The original Promise/A proposal had an optional method to attach callbacks without async-chaining.
To make it clear, what happened previously was that the non async-chaining
then was pointless because we alreay had
progress. If we make them async-chaining now, then we need the old
then back in some form which is a step backward.
Also, let me re-iterate that an async-chaining
done would be pretty useless since you can just call
then with a single argument already.
I know you've done most of the current implementation. Please try to look at this API from a standpoint of an outsider. A person who looks at your API from the outside. Methods .done/.fail really look like aliases to .then.
I don't think outsiders are that confused. In 3 years, I don't remember having been asked about the behaviour of
progress in relation to async chaining. I suppose most developers are quite happy to have a simple and efficient means to attach callbacks to the promise. In comparison, I've been literally harassed on twitter, on irc, by emails and at conferences about not being Promise/A(+) compliant since day one :P
Interestingly, I think people understand
fail all right but are more confused about