4 ms·
The author mentions jQuery's broken promises implementation and how it prevents the excellent chaining feature. I definitely see how jQuery's implementation di
by dos1 14y ago
The author mentions jQuery's broken promises implementation and how it prevents the excellent chaining feature. I definitely see how jQuery's implementation differs from the Promises/A spec. However, doesn't .pipe() in jQuery basically allow for the same chainability as .then() from Promises/A? Is there a difference I'm not aware of?
- Cogito 14y agoI think the main point there was that unless you check 'promises' given to you from other APIs and applications you can't rely on them conforming to the spec. As authors of Promises/A-consuming libraries, we would like to assume ... that something that is "thenable" actually behaves as a Promises/A promise, with all the power that entails. If you can make this assumption, you can write very extensive libraries that are entirely agnostic to the implementation of the promises they accept! Whether they be from Q, when.js, or even WinJS, you can use the simple composition rules of the Promises/A spec to build on promise behavior... Unfortunately, libraries like jQuery break this. This necessitates ugly hacks to detect the presence of objects masquerading as promises, and who call themselves in their API documentation promises, but aren't really Promises/A promises. If the consumers of your API start trying to pass you jQuery promises, you have two choices: fail in mysterious and hard-to-decipher ways when your compositional techniques fail, or fail up-front and block them from using your library entirely. This sucks.
- domenicd 14y agoNo, jQuery's `pipe` (or their `then` in >= 1.8) still does not do error handling. I updated the article a couple days ago to address this directly: --- This breaks down into four scenarios, depending on the state of the promise. Here we give their synchronous parallels so you can see why it's crucially important to have semantics for all four: - Fulfilled, fulfillment handler returns a value: simple functional transformation - Fulfilled, fulfillment handler throws an exception: getting data, and throwing an exception in response to it - Rejected, rejection handler returns a value: a catch clause got the error and handled it - Rejected, rejection handler throws an exception: a catch clause got the error and re-threw it (or a new one) Without these transformations being applied, you lose all the power of the synchronous/asynchronous parallel, and your so-called "promises" become simple callback aggregators. This is the problem with jQuery's current "promises": they only support scenario 1 above, omitting entirely support for scenarios 2–4. --- So you get chaining, sure; you can flatten your callback trees into callback lists. That's cool, I guess. But they're still missing the point, which is to allow composability not only of always-successful functions, but of functions that sometimes fail as well.
- masklinn 14y ago> This is the problem with jQuery's current "promises": they only support scenario 1 above, omitting entirely support for scenarios 2–4. Actually, `pipe` kind-of handles case 3 as well: if a promise is returned from either `pipe` handler it's used as replacement for the `pipe`'s resolution (a value merely replaces the existing resolution or rejection value), so promise.pipe(null, function () { return $.when(42); }); will replace a rejection of `promise` by a resolution to 42. Also, there's a mistake with the text I believe: > That means if you give a promise out to multiple consumers, they can interfere with its state. No, if you give a deferred to consumers they can alter it but the result of `.promise()` doesn't provide mutator methods, only state change callbacks. Promise producers are supposed to return the result of `.promise()`, returning a non-rejected and non-resolved Deferred directly is an error. And while — as you note — Deferred#then doesn't behave per-spec, Deferred.pipe does create and return a new promise. (jQuery's deferreds have other issues which your post hasn't touched, such as the very special handling of single-value resolutions.