Skip to content

Instantly share code, notes, and snippets.

@cowboy
Last active August 29, 2015 13:56
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cowboy/9281390 to your computer and use it in GitHub Desktop.
Save cowboy/9281390 to your computer and use it in GitHub Desktop.
Man, jQuery Deferreds annoy the fuck out of me.
// When a jQuery deferred is resolved with a single value, the arguments to
// the .then callback are the same as when .then is called directly on the
// deferred or on $.when(deferred) AND ALSO $.when(deferred, deferred).
var dfd = $.Deferred().resolve([1, 2, 3]);
dfd.then(function(a) {
console.log('[1a]', a); // [1, 2, 3]
});
$.when(dfd).then(function(a) {
console.log('[2a]', a); // [1, 2, 3]
});
$.when(dfd, dfd).then(function(a, b) {
console.log('[3a]', a, b); // [1, 2, 3] [1, 2, 3]
});
// When a jQuery deferred is resolved with multiple values, the arguments to
// the .then callback are the same as when .then is called directly on the
// deferred or on $.when(deferred) BUT NOT $.when(deferred, deferred).
var dfd = $.Deferred().resolve(1, 2, 3);
dfd.then(function(a, b, c) {
console.log('[1b]', a, b, c); // 1 2 3
});
$.when(dfd).then(function(a, b, c) {
console.log('[2b]', a, b, c); // 1 2 3
});
$.when(dfd, dfd).then(function(a, b) {
console.log('[3b]', a, b); // [1, 2, 3] [1, 2, 3]
});
// I mean, I get it. You want $.when(deferred) to be idempotent. Is that the
// right fancy word? Whatever, close enough. And spreading all those values
// across the $.when(deferred, deferred) callback would be insane. Arrays make
// sense there. But why then spread those values across the deferred.then or
// $.when(dfd) callback? Because it's magicsexy?
// Because jQuery Ajax requests are resolved with multiple values instead of
// with a single array value, the arguments to the $.when(req, req) callback
// behave very differently than the arguments to the req.then or $.when(req)
// callback. THIS REALLY CONFUSES PEOPLE. SERIOUSLY, I SEE IT ALL THE TIME.
var req = $.ajax('/');
req.then(function(resp, status, obj) {
console.log('[1c]', resp, status, obj); // response 'success' jqXHR
});
$.when(req).then(function(resp, status, obj) {
console.log('[2c]', resp, status, obj); // response 'success' jqXHR
});
$.when(req, req).then(function(a, b) {
console.log('[3c]', a, b); // [response, 'success', jqXHR] [response, 'success', jqXHR]
});
// And because the $.Deferred() factory builds new deferred objects from
// scratch without any of the internal mechanics or some kind of prototype
// exposed, it's impossible to, say, override the Deferred resolve / reject
// method with one that converts multiple values into an array before
// actually resolving / rejecting.
// Here's a "plugin" that works around this annoyance by throwing away
// the extra values: 'success' & jqXHR, just leaving the response.
$.makeAjaxResultLessShitty = String;
var req = $.ajax('/').then($.makeAjaxResultLessShitty);
req.then(function(a) {
console.log('[1d]', a); // response
});
$.when(req).then(function(a) {
console.log('[2d]', a); // response
});
$.when(req, req).then(function(a, b) {
console.log('[3d]', a, b); // response response
});
// Anyways, this all begs the question:
// WHY RESOLVE JQUERY DEFERREDS WITH MULTIPLE VALUES?
// (Arrays work pretty darned well)
@cowboy
Copy link
Author

cowboy commented Mar 1, 2014

A new API that uses the emerging Promise standard sounds fantastic!

Also, I think that setting users' expectations in the ways I've suggested sounds fantastic, too.

Win/win!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment