A cancelable promise wrapper allows you to prevent promise handlers from executing after cancellation. This is useful for avoiding state updates in unmounted React components or canceling outdated API responses.
β Implementation
function makeCancelable(promise) { let hasCanceled = false; const wrapped = new Promise((resolve, reject) => { promise .then((val) => (hasCanceled ? reject({ canceled: true }) : resolve(val))) .catch((err) => (hasCanceled ? reject({ canceled: true }) : reject(err))); }); return { promise: wrapped, cancel() { hasCanceled = true; } }; }
π§ͺ Example:
const task = new Promise((res) => setTimeout(() => res("Done"), 1000)); const cancelable = makeCancelable(task); cancelable.promise .then(console.log) .catch((err) => { if (err.canceled) console.log("Canceled"); else console.error(err); }); setTimeout(() => cancelable.cancel(), 500); // cancel before it resolves
β Behavior:
- If
.cancel()is called before resolution, the promise rejects with{ canceled: true }. - If not canceled, resolves normally.
- Doesnβt abort the underlying task β only prevents
.then()/.catch()from running.
π§ Notes:
- This doesn't stop network/fetch/etc. β only suppresses result handlers .
- Use
AbortControllerfor cancelable fetch requests or actual task termination.
Quick Quiz
Test your understanding with 3 quick questions
Q1What does calling cancel() on a cancelable promise actually do?
Q2What happens when a cancelable promise is canceled before resolution?
Q3For truly canceling a fetch request (not just ignoring results), what should you use?