Ch. 1 · JavaScript

JavaScript Promise Finally and Error Preservation

JavaScript Promise Finally and Error Preservation. Learn the reasoning, a practical example, common mistakes and an interview exercise.

~2 min readintermediateupdated Oct 3, 2026

Finally performs cleanup and normally preserves the previous result. A thrown error or rejected promise in cleanup replaces the earlier outcome.

Step-by-step walkthrough

Step 1: Separate result work from cleanup

Successful transformation belongs in then or after await. Cleanup belongs in finally when it must happen for success and failure. Keep those responsibilities distinct so a returned data value is not confused with an ignored cleanup return value.

Step 2: Trace the preserved outcome

An ordinary finally callback passes through the previous fulfillment value or rejection reason. Throwing or returning a rejected promise from cleanup changes the chain to that new failure. This is useful to understand when a cleanup error masks the original problem.

Step 3: Protect the primary failure

Cleanup itself should have an intentional failure policy. Record a secondary release error without losing the original operation error when that is the desired contract. Also ensure cleanup belongs to the current resource owner rather than clearing another request’s state.

Worked scenario

A spinner cleanup leaves the response intact unless hiding the spinner itself throws.

const value = await Promise.resolve(7).finally(() => 99);
console.log(value); // 7
try {
  await Promise.reject(new Error('request failed'))
    .finally(() => { throw new Error('cleanup failed'); });
} catch (error) {
  console.log(error.message); // cleanup failed
}
JavaScript

Walk through the example

The first cleanup return does not replace seven. The second cleanup throws, so that error becomes the chain’s rejection. A spinner callback that cannot fail is simple; resource cleanup that can fail needs a deliberate way to retain both the operation failure and release failure for diagnostics.

Common mistake

Returning a normal value from finally does not transform the result. Catch without rethrowing may turn failure into success.

Verify the behavior

Test fulfilled and rejected inputs, synchronous cleanup throws and asynchronous cleanup rejection. For UI cleanup, overlap two operations and verify an obsolete operation cannot clear the current operation’s loading state or resource reference.

Interview exercise

Separate transformation from cleanup.

Answer and reasoning

Transform in then or after await, release resources in finally, and keep cleanup from obscuring the primary error.

Follow-up discussion

Why not return the transformed response in finally? Its normal return is ignored for that purpose. Does finally mean success? No: it runs after either outcome and normally preserves that outcome. Observe success or failure through the appropriate continuation.

Continue learning

Compare the scenario with the JavaScript interview questions and test your understanding with the JavaScript MCQs. For terminology and implementation details, consult the reference material.

More in JavaScript

read ✓JavaScript · mid

JavaScript Date and Timezone Pitfalls

Parse and format dates without timezone surprises: zero-based months, date-only versus date-time parsing, and why UTC storage avoids drift.

~3 min readread →
esc