class HD{
static PENDING='pending';
static FULFILLED='fulfilled';
static REJECTED='rejected';
constructor(executor){
this.status=HD.PENDING;
this.value=null;
this.callbacks=[];
try{
executor(this.resolve.bind(this),this.reject.bind(this));
}catch(error){
this.reject(error)
}
}
resolve(value){
if(this.status==HD.PENDING){
this.status=HD.FULFILLED;
this.value=value;
setTimeout(()=>{
this.callbacks.map(callback=>{
callback.onFulfilled(value)
})
})
}
}
reject(reason){
if(this.status==HD.PENDING){
this.status=HD.REJECTED;
this.value=reason;
setTimeout(()=>{
this.callbacks.map(callback=>{
callback.onReject(reason)
})
})
}
}
then(onFulfilled,onRejected){
if(typeof onFulfilled !== "function"){
onFulfilled=()=>this.value
}
if(typeof onRejected !== "function"){
onRejected=()=>this.value
};
return new HD((resolve,reject)=>{
if(this.status==HD.PENDING){
this.callbacks.push({
onFulfilled:value=>{
this.parse(onFulfilled(value),resolve,reject)
},
onRejected:value=>{
this.parse(onRejected(value),resolve,reject)
},
})
}
if(this.status==HD.FULFILLED){
setTimeout(()=>{
this.parse(onFulfilled(this.value),resolve,reject)
})
}
if(this.status==HD.REJECTED){
setTimeout(()=>{
this.parse(onRejected(this.value),resolve,reject)
});
}
})
}
parse(result,resolve,reject){
try {
if(result instanceof HD){
result.then(resolve,reject)
}else{
resolve(result)
}
}catch(error){
reject(error);
}
}
static resolve(value){
return new HD((resolve,reject)=>{
if(value instanceof HD){
value.then(resolve,reject)
}else{
resolve(value);
}
})
}
static reject(value){
return new HD((resolve,reject)=>{
reject(value)
})
}
static all(promises){
const values=[]
return new HD((resolve,reject)=>{
promises.forEach(promise=>{
promise.then(
value=>{
values.push(value);
if(values.length==promises.length){
resolve(values)
}
},
reason=>{reject(reason)}
)
})
})
};
static race(promises){
return new HD((resolve,reject) => {
promises.map( promise=>{
promise.then(
value=>{resolve(value)},
reason=>{reject(reason)}
);
}
)
})
}
}