finally(): Why It Can’t Change a Promise Result
A common misconception is that finally() behaves likethen(). In reality, it doesn’t receive values, ignores return values, and only affects a promise in very specific cases.
finally() doesn’t receive arguments
Let’s start with a quick quiz:
Question: What will appear in the console?
Wait, think about it!
If you think the answer is"Hi, Sasha!Whats up?", that assumption is wrong.
How finally() works under the hood
The finally method doesn’t have its own low-level implementation in the Promise specification.
Under the hood, it simply delegates to then, using the same callback for both success and failure:
promise.finally(onDone); // is roughly equivalent to promise.then(onDone, onDone);Because of this, onDone does not receive any arguments(no resolved value, no rejection reason).
Since no value is passed, the parameter remains undefined.
Correct answer:undefinedWhats up?
What happens to the Promise value after finally()?
Another quiz:
Question: What will be logged?
Answer: "Hi, Sasha!"
The value returned from finally() is completely ignored.
Key rule:
finally()does not change a Promise’s value. It exists for side effects only (cleanup, logging, metrics, etc.).
Why the returned value from finally() is ignored
finally()doesn’t receive the resolved value- It can’t pass a new value down the chain
- The Promise continues with the value from the last
then()orcatch()
Takeaways so far
- Since
finally()doesn't get any arguments, any value used inside it isundefined. - The return value from
finally()is ignored and does not affect the nextthen(). - The Promise keeps the value from the last
then()orcatch()beforefinally().
Can finally() change the Promise state?
Questions:
- What is the final Promise state?
- What will be logged:
"OK"or"Something went wrong"?
Despite expectations, the output is"Something went wrong", and the Promise is rejected.
Why does this happen?
Important clarification:finally() does not change a Promise’s state by default.
However, if an error is thrown inside finally(), or it returns a rejected Promise, that error overrides the previous state.
Returning a rejected Promise from finally()
Even without throwing an error, the result is still"Something went wrong".
Returning a rejected Promise from finally() also changes the Promise state.
Why does this work if return values are ignored?
Because finally() is implemented using then():
promise.finally(onDone); // roughly equivalent to promise.then(onDone, onDone);Expanded version of the example:
When the rejected Promise propagates, it overrides the previous resolved state—just like throwing an error.
If finally() returns a resolved Promise, the chain waits for it, then continues with the original value.
Final takeaways
finally()does not receive arguments; values inside it areundefined.- The return value from
finally()is ignored and does not alter the Promise result. - The Promise keeps the previous value or rejection reason unless:
- An error is thrown inside
finally() - A rejected Promise is returned from
finally()
- An error is thrown inside