class PstPromise {
constructor(executor) {
this.promiseState = "pending"
this.resolveValue = null
this.rejectValue = null
this.onFulfilledQueue = []
this.onRejectedQueue = []
let resolve = (value) => {
if (this.promiseState === "pending") {
if (this.promiseState !== "pending") return
queueMicrotask(() => {
this.promiseState = "fulfilled"
this.resolveValue = value
this.onFulfilledQueue.forEach((fn) => {
fn(this.resolveValue)
})
})
}
}
let reject = (value) => {
if (this.promiseState == "pending") {
if (this.promiseState !== "pending") return
queueMicrotask(() => {
this.promiseState = "rejected"
this.rejectValue = value
this.onRejectedQueue.forEach((fn) => {
fn(this.rejectValue)
})
})
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
then(onFulfilled, onRejected) {
return new PstPromise((resolve, reject) => {
onRejected = typeof onRejected === 'function' ? onRejected : (error) => { throw error};
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => {value}
if (this.promiseState === "pending") {
this.onFulfilledQueue.push(() => {
try {
const value = onFulfilled(this.resolveValue)
if(value instanceof PstPromise){
value.then(resolve,reject)
}else{
resolve(value)
}
} catch (error) {
reject(error)
}
})
this.onRejectedQueue.push(() => {
try {
const value = onRejected(this.rejectValue)
if(value instanceof PstPromise){
value.then(resolve,reject)
}else{
resolve(value)
}
} catch (error) {
reject(error)
}
})
}
if (this.promiseState == "fulfilled" && onFulfilled) {
try {
const value = onFulfilled(this.resolveValue)
if(value instanceof PstPromise){
value.then(resolve,reject)
}else{
resolve(value)
}
} catch (error) {
reject(error)
}
}
if (this.promiseState == "rejected" && onRejected) {
try {
let value = onRejected(this.rejectValue)
if(value instanceof PstPromise){
value.then(resolve,reject)
}else{
resolve(value)
}
} catch (error) {
reject(error)
}
}
})
}
catch(onRejected){
return this.then(undefined,onRejected)
}
finally(onFinally){
return this.then(onFinally,onFinally)
}
static all(promises){
return new PstPromise((resolve,reject) => {
const values = [];
promises.forEach(promise => {
promise.then(res => {
values.push(res);
if(values.length > promises.length){
resolve(values)
}
},(err) => {
reject(err)
})
})
})
}
static allSettled(promises){
return new PstPromise((resolve,reject) => {
const results = [];
promises.forEach(promise => {
promise.then((res)=> {
results.push({status:'fulfilled',value:res})
},(err) => {
results.push({status:'rejected',value:err})
})
})
})
}
static race(promises){
return new PstPromise((resolve,reject) => {
promises.forEach(promise => {
promise.then(res => {
resolve(res)
},err => {
reject(err)
})
})
})
}
static any(promises){
return new PstPromise((resolve,reject) => {
let errValues = [];
promises.forEach(promise => {
promise.then(res => {
resolve(res)
},err => {
errValues.push(err)
if(errValues.length > promises.length){
reject(new AggregateError(errValues))
}
})
})
})
}
}
function request(url){
return new PstPromise((resolve,reject)=>{
setTimeout(() => {
resolve(url)
},2000)
})
}
request('http://why').then((res)=>{
return request(res+'.base.com')
}).then(res => {
console.log(res)
})