!Custom promise
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
class CustomPromise {
state = "PENDING";
value = undefined;
thenCallbacks = [];
errorCallbacks = [];
constructor(action) {
// Передаем методы, привязанные к контексту экземпляра
try {
action(this.resolver, this.reject);
} catch (err) {
this.reject(err);
}
}
static resolve(value) {
return new CustomPromise((resolve) => resolve(value));
}
static reject(reason) {
return new CustomPromise((_, reject) => reject(reason));
}
resolver = (value) => {
// Защита: изменить состояние можно только из PENDING
if (this.state !== "PENDING") {
return;
}
this.state = "RESOLVED";
this.value = value;
// Гарантируем асинхронность вызова (имитация микрозадачи)
queueMicrotask(() => {
this.thenCallbacks.forEach((callback) => callback(this.value));
});
}
reject = (value) => {
if (this.state !== "PENDING") {
return;
}
this.state = "REJECTED";
this.value = value;
queueMickrotask(() => {
this.errorCallbacks.forEach((callback) => callback(this.value));
});
}
then(callback) {
this.thenCallbacks.push(callback);
// Для полноценного чейнинга здесь должен возвращаться новый промис,
// но для простой асинхронности возврат this тоже сработает
return this;
}
catch(callback) {
this.errorCallbacks.push(callback);
return this;
}
}
// Тест (исправлен Math.random)
let promise = new CustomPromise((resolve, reject) => {
setTimeout(() => {
const rand = Math.ceil(Math.random() * 6);
if (rand > 2) {
resolve(`Success (Dropped: ${rand})`);
} else {
reject(`Error (Dropped: ${rand})`);
}
}, 1000);
});
promise
.then((res) => console.log("Result:", res))
.catch((err) => console.error("Caught:", err));
promise.then((res) => console.log(res)).catch(err => console.log(err));
console.log("Hello World!");
JavaScript
INFO