$.ajax takes success and error options, so most code passes callbacks in and stops there. It also returns a jqXHR, which has implemented the Deferred interface since 1.5 — meaning the function that makes the request does not have to know what happens with the answer.
// the option callback: only attachable at the call site
$.ajax({ url: '/basket', success: render });
// the returned jqXHR: attachable later, by whoever needs it
function loadBasket() {
return $.ajax({ url: '/basket', dataType: 'json' });
}
loadBasket().done(render).fail(showError).always(hideSpinner);
$.when(loadBasket(), $.get('/shipping'))
.done(function (basket, shipping) {
// each argument is [ data, statusText, jqXHR ]
});
Returning the jqXHR is the whole gain: loadBasket() stops deciding what happens next, and two callers can want different things from the same request. The trap is $.when. Given a single deferred it passes the resolution arguments through spread out, so the handler receives data, statusText, jqXHR; given two or more it passes one array per deferred. Adding a second request therefore changes the shape of the first argument without any error, and the code that read basket.lines now reads it off an array. Take the data as basket[0] from the start. .pipe() still works but .then() has returned a filtered promise since 1.8, so .pipe() is the one to stop writing.