class MyPromise {
constructor(executor) {
this.state = 'pending';
this.id = id++
this.value = undefined;
this.error = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
setTimeout(() => {
this.onFulfilledCallbacks.forEach((callback) => callback(this.value));
});
}
};
const reject = (error) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.error = error;
this.onRejectedCallbacks.forEach((callback) => callback(this.error));
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
const onFulfilledCallback = (value) => {
try {
if (typeof onFulfilled === 'function') {
const result = onFulfilled(value);
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} else {
resolve(value);
}
} catch (error) {
reject(error);
}
};
const onRejectedCallback = (error) => {
try {
if (typeof onRejected === 'function') {
const result = onRejected(error);
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} else {
reject(error);
}
} catch (error) {
reject(error);
}
};
if (this.state === 'fulfilled') {
setTimeout(() => {
onFulfilledCallback(this.value);
});
} else if (this.state === 'rejected') {
setTimeout(() => {
onRejectedCallback(this.error);
});
} else {
this.onFulfilledCallbacks.push(onFulfilledCallback);
this.onRejectedCallbacks.push(onRejectedCallback);
}
});
}
catch (onRejected) {
return this.then(undefined, onRejected);
}
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = [];
let completedCount = 0;
for (let i = 0; i < promises.length; i++) {
promises[i].then((value) => {
results[i] = value;
completedCount++;
if (completedCount === promises.length) {
resolve(results);
}
}).catch(reject);
}
});
}
static race(promises) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve).catch(reject);
}
});
}
}