class MP{
constructor(executor){
const resolve = (data)=>{
if(this.status === 'pending'){
this.result = data
this.status = 'fulfilled'
while(this.onResolveCallbacks.length){
this.onResolveCallbacks.shift()(data)
}
}
}
const reject = (reason)=>{
if(this.status === 'pending'){
this.result = reason
this.status = 'rejected'
while(this.onRejectCallbacks.length){
this.onRejectCallbacks.shift()(reason)
}
}
}
this.status = 'pending'
this.result = null
this.onResolveCallbacks = []
this.onRejectCallbacks = []
try{
executor(resolve,reject)
}catch(err){
reject(err)
}
}
then(onResolve,onReject){
onResolve = typeof onResolve === 'function'?onResolve:val=>val
onReject = typeof onReject === 'function'?onReject : reason => {throw reason}
const thenPromise = new MP((resolve, reject)=>{
const resolvePromise = cb=>{
setTimeout(()=>{
const x = cb(this.result)
try{
if(x === thenPromise){
throw new Error('不能返回自身')
}else if(x instanceof MP){
x.then(resolve, reject)
}else {
resolve(x)
}
}catch(err){
reject(err)
throw err
}
})
}
if(this.status === 'pending'){
this.onResolveCallbacks.push(()=>resolvePromise(onResolve))
this.onRejectCallbacks.push(resolvePromise.bind(this,onReject))
} else if(this.status === 'fulfilled') {
resolvePromise(onResolve)
} else if(this.status === 'rejected') {
resolvePromise(onReject)
}
})
return thenPromise
}
}
const mp = new MP(resolve=>{
setTimeout(()=>{resolve(1)},1000)
})
mp.then(data=>{
console.log('!',data)
})
mp.then(data=>{
console.log('?',data)
return new MP(resolve=>{
setTimeout(()=>{
resolve(3)
},2000)
})
}).then((e)=>{
console.log(e)
})
then(onResolve,onReject){
const thenPromise = new MP((resolve, reject)=>{
const resolvePromise = cb =>{
const x = cb(this.result)
if(x === thenPromise){
throw new Error('不能返回自身')
} else if(x instanceof MP){
x.then(resolve,reject)
} else {
resolve(x)
}
}
if(this.status === 'pending'){
this.onResolveCallbacks.push(resolvePromise.bind(this,onResolve))
this.onRejectCallbacks.push(resolvePromise.bind(this,onReject))
} else if(this.status === 'fulfilled'){
resolvePromise(onResolve)
} else if(this.status === 'rejected'){
resolvePromise(onReject)
}
})
return thenPromise
})