AJAX

$.ajax(url, settings) wraps XMLHttpRequest (AJAX with XMLHttpRequest) and returns a jqXHR, a Deferred with done(), fail() and always(). Key settings are method, data (objects are encoded by $.param()), dataType (json, html, text, script), headers, timeout and statusCode; $.ajaxSetup() sets defaults. The shorthands $.get(), $.post(), $.getJSON(), $.getScript() and $(el).load('page.html #part') cover common cases. Handlers for ajaxStart, ajaxSend, ajaxSuccess, ajaxError, ajaxComplete and ajaxStop on document observe every request, which suits a global spinner. jQuery 4 561 sends FormData bodies without extra settings. The demo serves JSON from a Blob URL, so it needs no server:

A JSON request, a failing request, global handlers and serializationHTMLLive
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<form hidden><input name="q" value="desk lamp"><input name="tag" value="led"></form>
<pre id="log" style="margin:0"></pre>
<script>
  const log = (msg) => $('#log').append(document.createTextNode(`${msg}\n`));
  const url = URL.createObjectURL(new Blob([JSON.stringify([{ name: 'Desk lamp' }])]));
  $(document).on('ajaxStart', () => log('ajaxStart: show spinner'))
    .on('ajaxStop', () => log('ajaxStop: hide spinner'));
  log(`serialize(): ${$('form').serialize()}; $.param(): ${$.param({ ids: [1, 2] })}`);
  $.ajax(url, { dataType: 'json', timeout: 5000 })
    .done((items, status, xhr) => log(`done: ${items[0].name}, ${status}, HTTP ${xhr.status}`));
  $.get(`${url}-missing`).fail((xhr, status) => log(`fail: ${status}, HTTP ${xhr.status}`));
</script>
Browser output of Listing 8.67
Browser output of 67

.load() without a selector runs the fragment's scripts, so load only trusted pages.