Core · jQuery-compatible

Timeouts, aborts & retries

Networks fail. jsKjs gives you real status codes, automatic timeouts that abort the request, a manual .abort(), and everything you need to retry politely.

Any non-2xx response rejects with an Error that carries .status and the parsed body as .data. A timeout option aborts the underlying fetch through an AbortController, and the rejection's name is 'AbortError'. Call .abort() on the returned promise to cancel yourself — useful when a newer search makes an older one irrelevant.

The flaky endpoint below fails about 60% of the time at random, on the server, so the retry demo is honest: sometimes it succeeds first try, sometimes it needs three.

Live · Failure lab

Pick a failure.
View the source for this demo
HTML
<div class="row">
  <button type="button" id="te-404">GET a 404</button>
  <button type="button" id="te-500">GET a 500</button>
  <button type="button" id="te-timeout">Timeout 800 ms vs 3 s server</button>
  <button type="button" id="te-abort">Abort after 400 ms</button>
  <button type="button" id="te-retry">Retry with backoff</button>
</div>
<pre class="out" id="te-out" aria-live="polite">Pick a failure.</pre>
JavaScript
const out = msg => $('#te-out').text(msg);

$('#te-404').on('click', () =>
  $.ajax('/api/fail.php?code=404').fail(err => out('.fail() → status ' + err.status + ': ' + err.data)));

$('#te-500').on('click', async () => {
  try { await $.get('/api/fail.php?code=500'); }
  catch (err) { out('try/catch → status ' + err.status); }
});

$('#te-timeout').on('click', () => {
  out('Waiting up to 800 ms…');
  $.ajax({ url: '/api/slow.php?ms=3000', timeout: 800 })
    .fail(err => out(err.name + ' — gave up after 800 ms; the server needed 3 s.'));
});

$('#te-abort').on('click', () => {
  out('Started; aborting in 400 ms…');
  const req = $.ajax('/api/slow.php?ms=3000');
  req.fail(err => out('.abort() → ' + err.name));
  setTimeout(() => req.abort(), 400);
});

async function withRetry(url, tries = 4) {
  for (let i = 1; i <= tries; i++) {
    try { return { data: await $.get(url), attempt: i }; }
    catch (err) {
      out('Attempt ' + i + ' → ' + err.status + (i < tries ? ', retrying in ' + 200 * 2 ** i + ' ms…' : ''));
      if (i === tries) throw err;
      await new Promise(r => setTimeout(r, 200 * 2 ** i));
    }
  }
}

$('#te-retry').on('click', async () => {
  try {
    const { data, attempt } = await withRetry('/api/flaky.php');
    out('Succeeded on attempt ' + attempt + ': ' + data);
  } catch (err) { out('Gave up after 4 attempts.'); }
});

More examples

Cancel stale searches

JavaScript
let pending;
$('#q').on('input', $.debounce(async function () {
  pending?.abort();                       // cancel the previous request
  pending = $.get('/api/search', { q: this.value });
  try { $('#results').html(await pending); } catch (e) { /* aborted or failed */ }
}, 200));

API

$.ajax(url | options [, options]) → Promise

Full-control requests. Options: url, method (or jQuery’s type), data (object → urlencoded or querystring; FormData; string), json: true (send JSON body), dataType (’json’ | ’auto’), headers, timeout (ms, auto-aborts), credentials, and callbacks success(data, status, res), error(err), complete(). The promise also has .abort().

Reference: $.ajax() →

Related features