AJAX with Fetch

fetch(resource, options) returns a promise for a Response. It is Baseline Widely available (since September 2019) and shares Request, Response and Headers with the Cache API (The Cache API). Read a body once with text(), json(), blob() or bytes(), or clone() it first. The promise rejects only on a network failure, CORS refusal or abort; a 404 resolves, so check response.ok.

Fetch with Request, Headers, error checks and a timeoutJavaScript
async function getJSON(input, options = {}) {
  const response = await fetch(input, { signal: AbortSignal.timeout(2000), ...options });
  if (!response.ok) throw new Error(`HTTP ${response.status} ${response.statusText}`);
  return response.json();
}
const request = new Request('/api/notes', {
  method: 'POST',
  headers: new Headers({ 'Content-Type': 'application/json' }),
  body: JSON.stringify({ text: 'Buy milk' }),
  priority: 'high',                               // 'high' | 'low' | 'auto'
});
console.log('created:', await getJSON(request));
const report = (err) => console.log(`${err.name}: ${err.message}`);
await getJSON('/api/missing').catch(report);        // server answers 404
await getJSON('/api/slow').catch(report);           // server needs 5 seconds

In headless Chrome 152 1 , against a small Node server, it logs:

Output of 3
created: {id: 1, text: Buy milk}
Error: HTTP 404 Not Found
TimeoutError: signal timed out

controller.abort() rejects with AbortError, and AbortSignal.any() combines signals (Practical Asynchrony). The priority hint is Baseline Newly available (since October 2024). keepalive: true lets up to 64 KiB of requests finish after the page closes; Firefox 555 added it last, in version 133.