Clear thinking · Useful delivery · Work built to last

PEN BEAM / COPY-READY EXAMPLE

Fetch Data with a Timeout and Error State

JavaScriptAutomationModern browsers with Fetch and AbortController

Request an endpoint with a timeout and explicit HTTP/network error handling using vanilla JavaScript.

What this snippet does

Requests data with a timeout, checks the HTTP status and separates network failures from application-level errors.

JavaScript / source code
async function fetchJson(url, timeoutMs = 8000) {
  const controller = new AbortController();
  const timeoutId = window.setTimeout(() => controller.abort(), timeoutMs);
  try {
    const response = await fetch(url, {
      method: 'GET',
      headers: { Accept: 'application/json' },
      signal: controller.signal,
      credentials: 'same-origin'
    });
    if (!response.ok) {
      throw new Error(`Request failed with HTTP ${response.status}`);
    }
    return await response.json();
  } finally {
    window.clearTimeout(timeoutId);
  }
}

const statusElement = document.querySelector('[data-fetch-status]');
const listElement = document.querySelector('[data-fetch-list]');

function showStatus(message) {
  if (statusElement) statusElement.textContent = message;
}

function renderItems(items) {
  if (!listElement || !Array.isArray(items)) return;
  listElement.replaceChildren();
  items.forEach((item) => {
    const row = document.createElement('li');
    const renderedTitle = item && item.title && typeof item.title.rendered === 'string'
      ? item.title.rendered
      : (item && typeof item.title === 'string' ? item.title : 'Untitled item');
    // Convert encoded title markup to text; never inject API strings as HTML.
    row.textContent = new DOMParser().parseFromString(renderedTitle, 'text/html').body.textContent || 'Untitled item';
    listElement.appendChild(row);
  });
}

fetchJson('/wp-json/wp/v2/posts?per_page=5')
  .then((items) => {
    renderItems(items);
    showStatus('Content loaded.');
  })
  .catch((error) => {
    showStatus(error.name === 'AbortError'
      ? 'The request timed out. Please retry.'
      : 'The request could not be completed. Please retry.');
  });

Where to place it

Add the required markup (an element with data-fetch-status and a list with data-fetch-list), then place this JavaScript in an enqueued theme script. Replace the endpoint and item-field mapping to match your application.

Back up the relevant file or settings first. Apply the change on staging, verify behavior, and retain a rollback path before production deployment.

What to check before deploying

  • Confirm the target endpoint is public or uses an authenticated server-side route; never expose API keys in browser code.
  • Test the timeout, non-2xx response and malformed JSON paths, and confirm the UI reports useful errors.
  • Check that returned text is inserted with textContent rather than injected as HTML; test mobile and keyboard use.

Related snippets

Need this adapted to your project? Start a project