← Back to question bank
QuizFoundationEasy#1005 · 15m

Explain Promise failure propagation

Explain then/catch/finally behavior across async boundaries. Then apply it to a realistic product screen where a user action, browser behavior, and rendering timing all matter.

Answer Strategy

For promise failure propagation, do not answer like a glossary entry. State the rule, show where it appears in product UI, then name the user-visible bug that happens when the rule is misunderstood.

A strong foundation answer has three layers: the browser or language model, a tiny code example, and a frontend consequence such as stale state, broken focus, blocked input, unsafe data, or flaky tests.

The reference example below is intentionally small but production-shaped: it names the boundary, protects the failure mode, and includes a test that proves the rule instead of relying on explanation alone.

Reference Example: Promise Failure Boundary

Use a result union so async failures are explicit and the UI cannot accidentally render partial success as truth.

type LoadResult<T> =
  | { ok: true; data: T }
  | { ok: false; message: string; retryable: boolean };

async function loadJson<T>(url: string, signal?: AbortSignal): Promise<LoadResult<T>> {
  try {
    const response = await fetch(url, { signal, headers: { accept: 'application/json' } });
    if (!response.ok) {
      return { ok: false, message: 'HTTP ' + response.status, retryable: response.status >= 500 };
    }
    return { ok: true, data: (await response.json()) as T };
  } catch (error) {
    if (signal?.aborted) {
      return { ok: false, message: 'Request cancelled', retryable: false };
    }
    return {
      ok: false,
      message: error instanceof Error ? error.message : 'Unknown failure',
      retryable: true,
    };
  }
}

Testing Strategy

Convert the answer into observable behavior. In a mid-senior interview, say which behaviors are covered by unit tests, interaction tests, accessibility checks, and one browser smoke path.

Rule
State the browser, JavaScript, TypeScript, CSS, security, or accessibility rule in one sentence.
Product bug
Connect the rule to a concrete UI failure: stale data, blocked input, broken focus, layout shift, or unsafe trust boundary.
Proof
Use a tiny test, trace, or code review checklist item that would catch the misunderstanding.
test('loadJson turns rejected promises into explicit UI state', async () => {
  vi.stubGlobal('fetch', vi.fn(() => Promise.reject(new Error('network down'))));

  await expect(loadJson<{ id: string }>('/api/user')).resolves.toEqual({
    ok: false,
    message: 'network down',
    retryable: true,
  });
});

Interviewer Signal

Shows whether you understand promise failure propagation as an operating model, not as memorized trivia.

Constraints

  • Use one concrete browser or React-facing example.
  • Name the failure mode a production user would notice.
  • Keep the first answer under two minutes before expanding.

Model Answer Shape

  • Start with the rule: then/catch/finally behavior across async boundaries.
  • Tie the rule to ownership: what runs in render, what runs after paint, what is external state, and what must be cleaned up.
  • Close with the smallest test, trace, or code review check that would catch the bug.

Tradeoffs

  • A short interview answer is easier to follow, but a senior answer must still name the edge case.
  • Framework vocabulary helps only after the browser or language rule is clear.

Edge Cases

  • Slow devices where timing bugs become visible.
  • Repeated user actions before async work settles.
  • Browser defaults that differ from custom component behavior.

Testing And Proof

  • Unit-test the pure decision when possible.
  • Use an interaction test for focus, keyboard, timing, or cleanup behavior.

Follow-Ups

  • How would this change in a React component?
  • What would you log or profile if this broke in production?