Last active
January 22, 2026 13:04
-
-
Save carefree-ladka/2c48e89c0ac56a747a68b3b8384cdb8e to your computer and use it in GitHub Desktop.
Promise Impl for Interviews
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class MyPromise { | |
| constructor(executor) { | |
| this.fulfilledHandlers = []; | |
| this.rejectedHandlers = []; | |
| this.state = "pending"; | |
| this.value = undefined; | |
| const resolve = (value) => { | |
| if (this.state !== "pending") return; | |
| // self-resolution check | |
| if (value === this) { | |
| reject(new TypeError("Chaining cycle detected for promise")); | |
| return; | |
| } | |
| this.state = "fulfilled"; | |
| this.value = value; | |
| queueMicrotask(() => { | |
| this.fulfilledHandlers.forEach((cb) => cb(value)); | |
| }); | |
| }; | |
| const reject = (reason) => { | |
| if (this.state !== "pending") return; | |
| this.state = "rejected"; | |
| this.value = reason; | |
| queueMicrotask(() => { | |
| this.rejectedHandlers.forEach((cb) => cb(reason)); | |
| }); | |
| }; | |
| try { | |
| executor(resolve, reject); | |
| } catch (e) { | |
| reject(e); | |
| } | |
| } | |
| then(onFulfilled, onRejected) { | |
| return new MyPromise((resolve, reject) => { | |
| const fulfilled = (v) => { | |
| try { | |
| const result = typeof onFulfilled === "function" ? onFulfilled(v) : v; | |
| result instanceof MyPromise | |
| ? result.then(resolve, reject) | |
| : resolve(result); | |
| } catch (e) { | |
| reject(e); | |
| } | |
| }; | |
| const rejected = (err) => { | |
| try { | |
| if (typeof onRejected === "function") { | |
| const result = onRejected(err); | |
| result instanceof MyPromise | |
| ? result.then(resolve, reject) | |
| : resolve(result); | |
| } else { | |
| reject(err); | |
| } | |
| } catch (e) { | |
| reject(e); | |
| } | |
| }; | |
| if (this.state === "fulfilled") { | |
| queueMicrotask(() => fulfilled(this.value)); | |
| } else if (this.state === "rejected") { | |
| queueMicrotask(() => rejected(this.value)); | |
| } else { | |
| this.fulfilledHandlers.push(fulfilled); | |
| this.rejectedHandlers.push(rejected); | |
| } | |
| }); | |
| } | |
| catch(fn) { | |
| return this.then(null, fn); | |
| } | |
| finally(callback) { | |
| return this.then( | |
| (value) => MyPromise.resolve(callback()).then(() => value), | |
| (reason) => | |
| MyPromise.resolve(callback()).then(() => { | |
| throw reason; | |
| }) | |
| ); | |
| } | |
| static resolve(value) { | |
| if (value instanceof MyPromise) return value; | |
| return new MyPromise((resolve) => resolve(value)); | |
| } | |
| static reject(reason) { | |
| return new MyPromise((_, reject) => reject(reason)); | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
MyPromise Implementation Guide
1️⃣ Class Definition & Constructor
Explanation:
fulfilledHandlers→ stores all.thencallbacks for successrejectedHandlers→ stores all.then/.catchcallbacks for failurestate→ tracks the promise state:"pending"|"fulfilled"|"rejected"value→ holds either the resolved value or rejection reason2️⃣ Resolve & Reject Functions
Explanation:
queueMicrotaskensures the callbacks run asynchronously, even if resolve is called synchronously"fulfilled"and stores the valueExplanation:
3️⃣ Executor Try-Catch
Explanation:
4️⃣ then Method
Explanation:
.then()always returns a new promiseExplanation:
onFulfilledis a function, call it with the valueresult.then(resolve, reject)Explanation:
onRejectedprovided, propagate the rejection.catch()to work5️⃣ State Checks in then
Explanation:
6️⃣ catch Method
Explanation:
.catch(fn)is just shorthand for.then(null, fn)7️⃣ finally Method
Explanation:
callback()after success or failureMyPromise.resolve)8️⃣ Static resolve & reject
Explanation:
MyPromise.resolve(…)→ wraps a value into a promise (or returns if already a promise)MyPromise.reject(…)→ creates a rejected promise immediatelyExamples
Example 1 — Simple Resolve
Step-by-step:
resolve(10)queues microtask.thenruns → logs 10 → returns 20.thenruns → logs 20Example 2 — Nested Promises
Explanation:
Example 3 — finally
Output:
finallyruns callback after fulfillmentExample 4 — Rejection Handling
Output:
.catchhandles rejection.finallyalways runs✅ Summary
.thenreturns a new MyPromiseresolveandrejectcreate promises immediately