Suggest an editImprove this articleRefine the answer for “How to cancel a promise?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)A **promise** in JavaScript cannot be canceled directly: it starts running as soon as it is created, and there is no standard mechanism to stop a timer or `fetch`, because a promise is not a "stream" but a wrapper over a result that will arrive at some point. **Key point:** to "cancel" a promise, you have to cancel the action it represents, using `AbortController`, timeouts, or cancellation flags.Shown above the full answer for quick recall.Answer (EN)Image## Why a promise cannot be canceled directly When you create a promise, for example: ```javascript const promise = new Promise((resolve) => { setTimeout(() => resolve('done'), 5000); }); ``` It **starts running immediately** (from the moment the constructor is called), and there is no standard mechanism to "stop" the timer or `fetch`. In other words, a promise is not a "stream", but a **wrapper over a result** that will eventually arrive. --- ## Ways to implement cancellation ### 1. Use `AbortController` (the built-in standard) This is the most modern and "correct" way to cancel asynchronous operations, especially network ones (`fetch`). ```javascript const controller = new AbortController(); const { signal } = controller; fetch('/data', { signal }) .then(response => response.json()) .then(data => console.log('Success:', data)) .catch(err => { if (err.name === 'AbortError') { console.log('Request cancelled'); } else { console.error('Error:', err); } }); // cancel after 2 seconds setTimeout(() => controller.abort(), 2000); ``` What happens: - `AbortController` creates a control object; - `signal` is passed into `fetch`; - when `controller.abort()` is called, the request is aborted, and the promise rejects with `AbortError`. Works with: - `fetch()` - `ReadableStream`, `Response`, `Request` - many libraries that support signals (Axios, Deno, Node 18+, and others) --- ### 2. Create a "cancellable" promise manually You can wrap a regular promise in a structure that supports cancellation. ```javascript function makeCancellable(promise) { let isCancelled = false; const wrapped = new Promise((resolve, reject) => { promise .then((val) => (isCancelled ? reject({ cancelled: true }) : resolve(val))) .catch((error) => (isCancelled ? reject({ cancelled: true }) : reject(error))); }); return { promise: wrapped, cancel() { isCancelled = true; }, }; } ``` Usage example: ```javascript const { promise, cancel } = makeCancellable( new Promise((resolve) => setTimeout(() => resolve('Done'), 5000)) ); promise .then(console.log) .catch((e) => { if (e.cancelled) console.log('Cancelled by the user'); }); setTimeout(cancel, 2000); ``` After 2 seconds the promise will be "cancelled". Important: this is a **logical cancellation**, the operation itself (for example, `setTimeout` or `fetch`) still continues. --- ### 3. Use a flag inside an async function If you have an `async` function, you can check a "cancelled" flag: ```javascript let cancelled = false; async function runTask() { for (let i = 0; i < 5; i++) { if (cancelled) throw new Error('Cancelled'); await new Promise(r => setTimeout(r, 1000)); console.log('Step', i); } console.log('Done'); } const task = runTask(); setTimeout(() => (cancelled = true), 2500); ``` After 2.5 seconds execution stops. --- ### 4. Combine with `Promise.race()` (cancellation through a "race") You can set up a "race" between the operation and a cancellation timer: ```javascript function cancelable(promise, ms) { const cancel = new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), ms) ); return Promise.race([promise, cancel]); } cancelable(fetch('/api/data'), 2000) .then(res => res.json()) .then(console.log) .catch(console.error); ``` If `fetch` does not finish within 2 seconds, the promise rejects with a "Timeout" error. --- ## Summary | Method | What it does | Real cancellation | Good for | |---|---|---|---| | **AbortController** | Aborts operations that support signals | Yes | `fetch`, APIs with `signal` | | **makeCancellable()** | Creates a wrapper with a flag | No (logical cancellation) | Custom promises | | **Cancellation flag** | Checks "cancelled" manually | No | Loops, async functions | | **Promise.race()** | Settles with whichever promise wins | No, but convenient | Timeouts, competing tasks | --- **The bottom-line rule:** > You cannot "cancel" a promise in JS directly. > But you can **cancel the action** it represents, > using `AbortController`, timeouts, or cancellation flags.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.