Suggest an editImprove this articleRefine the answer for “Promise chaining”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Promise chaining is a sequence of asynchronous steps in which every `.then()`, `.catch()` and `.finally()` returns a new promise, so the result of one step becomes the input of the next.** Returning a plain value from `.then()` wraps it in `Promise.resolve(value)` and passes it on; returning a promise makes the chain wait for it; throwing an error skips every following `.then()` and jumps to the nearest `.catch()`. After a `.catch()` the chain continues as a successful one, and `.finally()` runs no matter what. ```javascript Promise.resolve(10) .then(n => n * 2) // 20 .then(n => n + 5) // 25 .then(n => console.log(n)) // 25 .catch(err => console.error(err)); ``` **Key point:** each step returns a new promise, values flow down the chain, and errors fall down to the first `.catch()`.Shown above the full answer for quick recall.Answer (EN)Image**Promise chaining is a sequence of asynchronous actions in which the result of one `.then()` is passed to the next one.** Every `.then()`, `.catch()` and `.finally()` returns a new promise, and that is what lets you build a linear processing flow without "callback hell". ## Theory ### TL;DR - Every `.then()` returns a **new promise**, which is why calls compose into a chain. - A value returned from `.then()` becomes the argument of the next `.then()`. - If `.then()` returns a promise, the chain waits for that promise to settle. - An error at any step skips all following `.then()` calls and goes to the nearest `.catch()`. - The chain continues after `.catch()`, because `.catch()` also returns a new promise. - `.finally()` always runs and does not change the value, unless it throws itself. ### Quick example ```javascript new Promise((resolve) => { setTimeout(() => resolve(10), 1000); }) .then((num) => { console.log('Step 1, received:', num); return num * 2; }) .then((num) => { console.log('Step 2, multiplied:', num); return num + 5; }) .then((result) => { console.log('Step 3, total:', result); }); ``` The output: ```text Step 1, received: 10 Step 2, multiplied: 20 Step 3, total: 25 ``` Every `.then()`: 1. receives the result of the previous step, 2. returns a **new promise**, 3. passes its result further down the chain. ### How it works under the hood 1. **The first promise** is created and enters `pending`. When `resolve(value)` is called it becomes `fulfilled`. 2. The first `.then()` receives `value` and returns a **new promise**, which now waits for the next result. 3. Every `.then()` in the chain **waits for the previous one to finish**, even when a new promise is returned inside it. An example with an asynchronous step: ```javascript Promise.resolve(1) .then((n) => { console.log('A:', n); return new Promise((resolve) => setTimeout(() => resolve(n + 1), 1000) ); }) .then((n) => { console.log('B:', n); return n * 3; }) .then((n) => console.log('C:', n)); ``` The output, after one second: ```text A: 1 B: 2 C: 6 ``` Here `.then()` recognises that it was handed a new promise, waits until it settles (`resolve`), and only then runs the next step of the chain. ### What you can return from then() | What `.then()` returns | What happens | | --- | --- | | **A plain value** | It is wrapped in `Promise.resolve(value)` | | **A promise** | The chain waits until it settles | | **An error (`throw`)** | The chain moves into `rejected` | | **Nothing** | It passes `undefined` on | An example that mixes values and promises: ```javascript Promise.resolve('A') .then((v) => v + 'B') // returns 'AB' .then((v) => Promise.resolve(v + 'C')) // waits for another promise .then((v) => v + 'D') .then(console.log); // ABCD ``` ### Errors in the chain If an error happens in any `.then()` (`throw` or a rejection), every following `.then()` is **skipped** and control moves to the **nearest** `.catch()`. ```javascript Promise.resolve(10) .then((x) => x / 2) .then(() => { throw new Error('Failure!'); }) .then(() => console.log('this will not run')) .catch((err) => console.error('Caught:', err.message)) .then(() => console.log('carrying on')); ``` The output: ```text Caught: Failure! carrying on ``` `.catch()` can also sit in the middle of a chain, to recover from an error: ```javascript Promise.reject('Failure') .catch((err) => { console.log('Caught:', err); return 'Recovered'; }) .then((v) => console.log('Next:', v)); ``` The output: ```text Caught: Failure Next: Recovered ``` `.catch()` returns a new promise too, so once the error is handled the chain carries on. ### finally() in the chain `finally()` runs **always**, whatever the outcome, and does not change the value unless it throws: ```javascript Promise.resolve('OK') .finally(() => console.log('Cleaning up...')) .then(console.log); ``` The output: ```text Cleaning up... OK ``` A full chain with an error, a recovery and a closing step: ```javascript Promise.resolve(1) .then((x) => x + 1) .then(() => { throw new Error('Oops!'); }) .catch((e) => { console.log('Error caught:', e.message); return 5; }) .then((x) => console.log('Result:', x)) .finally(() => console.log('Done')); ``` The output: ```text Error caught: Oops! Result: 5 Done ``` An analogy: a promise chain is an assembly line. Every `.then()` is a station where the part gets worked on; if something goes wrong, `.catch()` fixes the error and puts the part back on the line; at the end `.finally()` switches off the machines and sweeps the floor. ### Summary | Property | Description | | --- | --- | | Every `.then()` | Returns a new promise | | Values flow downwards | The result of one `.then()` goes into the next | | Errors | Fall down to the nearest `.catch()` | | `.finally()` | Runs in any case | | The chain | Lets you write asynchronous code linearly, with no nesting | ### Common mistakes - **Forgetting `return` inside `.then()`.** Without it the next step receives `undefined`, and the chain does not wait for a nested promise. - **Nesting `.then()` calls inside each other.** That recreates the callback hell the chain was meant to remove; return the promise instead of nesting. - **Placing `.catch()` only at the start.** It catches what happened above it, so errors from later steps slip past. - **Thinking `.catch()` breaks the chain.** After it the promise is successful again and the following `.then()` calls run. - **Assuming synchronous code inside `.then()` runs immediately.** Handlers always run as microtasks, after the current synchronous code. - **Losing errors without a trailing `.catch()`.** A chain without one produces an unhandled rejection, and in Node.js that can terminate the process.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.