AJAX helpers and why modern code moves on

The ajax family, its Deferred objects, and an honest comparison with fetch and the native APIs that replaced the rest of jQuery.

The ajax family

// the general form
$.ajax({
  url: '/api/items',
  method: 'GET',
  data: { page: 2, tag: 'css' },     // serialised to the query string
  dataType: 'json',                  // parses the response for you
  headers: { 'X-CSRF-Token': token },
  timeout: 8000
}).done(function (items) {
  render(items);
}).fail(function (xhr, status, error) {
  console.error(status, xhr.status);
}).always(function () {
  hideSpinner();
});

// shortcuts
$.get('/api/items', { page: 2 }, render);
$.post('/api/items', { name: 'new' }, render);
$.getJSON('/api/items.json').done(render);
$('#form').serialize();              // query-string from all fields
$('#form').serializeArray();         // [{ name, value }, ...]
OptionMeaning
dataTypejson, html, text, xml — how the body is parsed before your callback
contentTypeRequest header; set application/json and stringify the body yourself
cache: falseAppends a timestamp to GET requests — hides caching bugs rather than fixing them
beforeSendRuns before the request leaves; the classic place for a CSRF header
global: falseSuppresses the document-wide ajaxStart / ajaxError events
statusCodePer-status callbacks, for example { 404: onMissing }

done, fail and Deferreds

const req = $.getJSON('/api/items');

req.done(onOk).fail(onErr).always(cleanup);

// then() returns a new promise, so results can be transformed
req.then(function (items) {
  return $.getJSON('/api/items/' + items[0].id);
}).done(function (first) {
  console.log(first);
});

// wait for several requests
$.when($.getJSON('/a'), $.getJSON('/b'))
  .done(function (a, b) {
    render(a[0], b[0]);   // each argument is [data, statusText, xhr]
  });
  • A jQuery Deferred is promise-like: it has done, fail, then and always, but it is not a native Promise instance.
  • You cannot await a jQuery Deferred directly and expect a rejection to throw. Wrap it: await new Promise((res, rej) => req.done(res).fail(rej)).
  • $.when() resolves with one argument per request, each wrapped in an array — a frequent source of confusion.
  • jQuery 3 fixed the long-standing Deferred bug where exceptions inside then were swallowed, so behaviour now matches the Promises/A+ spec closely.

Why modern projects skip jQuery

jQuery solvedNative replacement available since
$(selector)querySelector / querySelectorAll
addClass / toggleClassclassList
.on() delegationaddEventListener with closest()
$.ajaxfetch, then axios or ky for niceties
animate()CSS transitions and the Web Animations API
$.eachArray.prototype.forEach / for...of
$.whenPromise.all / Promise.allSettled
$.extendObject.assign / spread
// jQuery version
$('.remove').on('click', function () {
  $(this).closest('li').addClass('gone');
});

// native equivalent, about the same length today
document.addEventListener('click', (e) => {
  const btn = e.target.closest('.remove');
  if (!btn) return;
  btn.closest('li').classList.add('gone');
});
  • Bundle cost: gzipped jQuery is roughly 30 KB before your own code — meaningful for a page that only needs a class toggle.
  • jQuery's plugins are its real moat: date pickers, validators, data tables and legacy vendor widgets still assume it is present.
  • Legacy browser support was the original reason to use it; that reason is gone now that evergreen browsers are the baseline.
  • Mixed codebases are the worst outcome — pick one style per feature and keep the two worlds from re-rendering the same DOM.
💡
The honest rule: jQuery is still a reasonable choice when you maintain existing jQuery code or depend on jQuery plugins, and a poor choice for a new page that only needs a dozen lines of native DOM work.

FAQ

Can I migrate from $.ajax to fetch without rewriting everything?
Yes. Wrap fetch in a helper that returns JSON, throws on non-OK statuses and handles timeouts, then replace the $.ajax calls one route at a time. The call sites shrink because the helper carries the common options.
Is jQuery still maintained?
Yes — the 3.x line still receives releases and security fixes, and the 4.x branch modernises internals. Maintenance is not abandonment, but new browser platforms have made most of its original job unnecessary.

Events, effects and attributes Requests with fetch

Last refreshed 2026-09-18.