Idle, loading, success, error

Every async operation moves through the same states. Idle before you start. Loading while it is in flight. Success when the data arrives. Error when it does not. Forgetting to render any of them is the most common bug in every frontend framework ever.

The four states

Every fetch walks this graph. Miss a state and your UI lies.

The fix is simple: for every async operation, design the loading and error UI first. A spinner is better than a frozen page. A readable error is better than a silent one. Users forgive slowness. They do not forgive confusion about whether anything is happening.

script.js
javascript
function setState(state, payload) {
  loading.style.display = state === 'loading' ? 'block' : 'none';
  errorMsg.classList.toggle('hidden', state !== 'error');
  if (state === 'error') errorMsg.textContent = payload;
  if (state === 'success') renderBooks(payload);
}

async function fetchBooks() {
  setState('loading');
  try {
    const res = await fetch('./books.json');
    if (!res.ok) throw new Error('HTTP ' + res.status);
    const data = await res.json();
    setState('success', data);
  } catch (err) {
    setState('error', err.message);
  }
}

All four states, wired up without any framework.

Quiz: Quiz

Loading practice…