Skip to main content

custom promise using classes

class CustomPromise {
constructor(executor) {
this.status = "pending";
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
this.onFinallyCallbacks = [];

const resolve = (value) => {
if (this.status === "pending") {
this.status = "fulfilled";
this.value = value;
this.onFulfilledCallbacks.forEach((callback) => callback(this.value));
this.onFinallyCallbacks.forEach((callback) => callback());
}
};

const reject = (reason) => {
if (this.status === "pending") {
this.status = "rejected";
this.reason = reason;
this.onRejectedCallbacks.forEach((callback) => callback(this.reason));
this.onFinallyCallbacks.forEach((callback) => callback());
}
};

try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}

then(onFulfilled, onRejected) {
return new CustomPromise((resolve, reject) => {
if (this.status === "fulfilled") {
try {
const result = onFulfilled ? onFulfilled(this.value) : this.value;
resolve(result);
} catch (error) {
reject(error);
}
}

if (this.status === "rejected") {
try {
const result = onRejected ? onRejected(this.reason) : this.reason;
reject(result);
} catch (error) {
reject(error);
}
}

if (this.status === "pending") {
this.onFulfilledCallbacks.push((value) => {
try {
const result = onFulfilled ? onFulfilled(value) : value;
resolve(result);
} catch (error) {
reject(error);
}
});

this.onRejectedCallbacks.push((reason) => {
try {
const result = onRejected ? onRejected(reason) : reason;
reject(result);
} catch (error) {
reject(error);
}
});
}
});
}

catch(onRejected) {
return this.then(null, onRejected);
}

finally(onFinally) {
return new CustomPromise((resolve, reject) => {
const handler = () => {
try {
onFinally();
if (this.status === "fulfilled") {
resolve(this.value);
} else if (this.status === "rejected") {
reject(this.reason);
}
} catch (error) {
reject(error);
}
};

if (this.status === "pending") {
this.onFinallyCallbacks.push(handler);
} else {
handler();
}
});
}
}

// Usage
const myPromise = new CustomPromise((resolve, reject) => {
setTimeout(() => {
resolve("Success!");
// or reject('Error!');
}, 1000);
});

myPromise
.then((value) => {
console.log(value); // Output: Success!
return "Next success";
})
.catch((reason) => {
console.error(reason);
})
.finally(() => {
console.log("Finally called");
});