const RESOLVE = 'resolved';
const REJECT = 'rejected';
const PENDING = 'pending';
const handlePromise = (result,newPromise,resolve,reject) => {
if(result === newPromise){
throw new Error("can't not return oneself")
}
if((typeof result === 'object' && typeof result !== null) || typeof result === 'function'){
let lock = false
try {
const then = result.then;
if(typeof then === 'function'){
then.call(result,(r)=>{
if(lock) return ;
handlePromise(r,newPromise,resolve,reject);
lock = true
},(e)=>{
if(lock) return ;
reject(e);
lock = true;
})
}else{
resolve(result)
}
} catch(error){
reject(error)
}
}else{
resolve(result)
}
}
class JJPromise {
status = PENDING;
result = undefined;
reason = undefined;
onResolveArr = [];
onRejectArr = [];
constructor(excution){
const resolve = (result) => {
if(this.status === PENDING){
this.result = result;
this.status = RESOLVE;
this.onResolveArr.map((fn) => fn())
}
}
const reject = (reason) => {
if(this.status === PENDING){
this.reason = reason;
this.status = REJECT;
this.onRejectArr.map((fn) => fn())
}
}
try {
excution(resolve,reject)
} catch(error) {
reject(error);
}
}
then(onResolved,onRejected){
onResolved = typeof onResolved === 'function' ? onResolved : (data) => data;
onRejected = typeof onRejected === 'function' ? onRejected : (err) => {
throw new Error(err)
}
const newPromise = new JJPromise((resolve,reject) => {
if(this.status === RESOLVE){
setTimeout(() => {
try {
const result = onResolved(this.result)
handlePromise(result,newPromise,resolve,reject);
} catch(error) {
reject(error)
}
},0)
}
if(this.status === REJECT){
setTimeout(() => {
try {
const result = onRejected(this.reason)
handlePromise(result,newPromise,resolve,reject);
} catch(error) {
reject(error)
}
},0)
}
if(this.status === PENDING){
this.onResolveArr.push(()=>{
try {
const result = onResolved(this.result)
handlePromise(result,newPromise,resolve,reject);
} catch(error) {
reject(error)
}
})
this.onRejectArr.push(()=>{
try {
const result = onRejected(this.result)
handlePromise(result,newPromise,resolve,reject);
} catch(error) {
reject(error)
}
})
}
})
return newPromise;
}
catch(onRejected){
return this.then(undefined,onRejected);
}
}
const test = new JJPromise((resolve,reject) => {
resolve('123')
})
test.then((res) => {console.log(res)})
console.log('1')
// 1
// 123