then, catch, finally
1. What then() does
promise.then(onFulfilled, onRejected);Purpose:
then() registers a handler for the promise's successful outcome - that is, when the promise transitions to the fulfilled state.
How it works:
- If the promise finished successfully (
resolve(value)), the first functiononFulfilled(value)is called; - If it finished with an error (
reject(error)), the second functiononRejected(error)is called (optional); - It returns a new Promise, allowing you to build chains.
Example:
new Promise((resolve) => {
setTimeout(() => resolve('Success!'), 1000);
})
.then((result) => {
console.log(result); // Success!
return 'Next step';
})
.then((value) => {
console.log(value); // Next step
});Every .then() returns a new promise, which can be continued as a chain.
What then() returns
| Case | Returns | Behavior |
|---|---|---|
| Returning a value | Promise.resolve(value) | Passes the result to the next .then() |
| Returning a promise | "unwraps" the promise | Waits until it settles |
An error (throw) | Promise.reject(error) | Goes to .catch() |
Example with an error:
Promise.resolve(10)
.then((x) => {
throw new Error('Problem!');
})
.catch((err) => console.error(err.message)); // Problem!2. What catch() does
promise.catch(onRejected);Purpose:
catch() catches errors in a promise chain -
both from the promise itself and from preceding .then() calls.
How it works:
- It is called if the promise is rejected;
- It returns a new promise, allowing the chain to continue.
Example:
new Promise((_, reject) => {
reject('Error');
})
.then(() => console.log('This will not run'))
.catch((err) => console.error('Caught:', err))
.then(() => console.log('Continuing on'));Output:
Caught: Error
Continuing onAfter .catch(), the chain continues as if the error had been handled.
Example: catching an error from .then()
Promise.resolve('OK')
.then(() => {
throw new Error('Oops!');
})
.catch((err) => console.error('Error caught:', err.message));.catch() catches all errors up the chain.
3. What finally() does
promise.finally(onFinally);Purpose:
finally() runs always,
regardless of whether the promise finished successfully (fulfilled)
or with an error (rejected).
It is used for cleanup, closing connections, hiding loaders, and so on.
How it works:
- It does not receive the result (
value) or the error (error); - It runs after
.then()or.catch(); - It returns a new promise with the same result as the original one.
Example:
fetch('/data.json')
.then((res) => res.json())
.catch(() => console.error('Loading error'))
.finally(() => console.log('Loading finished'));Even if there is an error, finally still runs:
Loading error
Loading finishedExample with a returned value
Promise.resolve('OK')
.finally(() => console.log('Always runs'))
.then((value) => console.log(value));Output:
Always runs
OKImportant:
If you throw an error (throw) inside finally,
it replaces the promise's result:
Promise.resolve('OK')
.finally(() => {
throw new Error('Error in finally');
})
.then(console.log)
.catch((err) => console.error(err.message)); // Error in finallySummary: comparison
| Method | When it is called | Receives an argument | Returns | Used for |
|---|---|---|---|---|
then() | on resolve (success) | the result (value) | a new Promise | handling the result |
catch() | on reject (error) | the error (error) | a new Promise | handling errors |
finally() | always (both on success and on error) | - | a new Promise | final actions |
Analogy
Imagine you ordered a pizza.
then()- the courier arrived, the pizza was delivered;catch()- the courier got lost, the order never arrived;finally()- you clean up the box and wash your hands, regardless of whether you got to eat or not.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.