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

@dmethvin, I know that part of what makes jQuery maintainers good at, well, maintaining jQuery is the mindset where, when a bug or weird behavior is encountered in a browser, you fix it. But you're talking about the way the internet works; there will always be outdated or incorrect blogs, StackOverflow advice and documentation scattered around the net. It's not your job as the maintainers of a small software library to fix the way people use the internet; it's your job to make a library with an awesome API. Fortunately, just like with every other software library they use, developers will figure out how to use it. I mean, jQuery has fantastic official documentation.

I understand about the plugin thing, I happen to maintain a tool that has thousands of plugins. Updating the tool sometimes breaks plugins, which people don't like. But fortunately, users can continue to use the old version of the tool until the plugin they want to use gets updated. People aren't forced to upgrade!

@dmethvin
Copy link

dmethvin commented Mar 1, 2014

Okay, so you're proposing a drastic breaking change to the existing API. Write some code that defines the way you want it to work. Explain why we should make that breaking change rather than creating a new API that uses the emerging Promise standard.

@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