todo
class P {
constructor(exector) {
if (typeof exector !== 'function')
throw TypeError(`Promise resolver ${arguments[0]} is not a function`)
this.status = 'pending'
this.value = null
this.resolveList = []
this.rejectList = []
try {
exector(this._resolve.bind(this), this._reject.bind(this))
} catch (e) {
this._reject(e)
throw e
}
}
_resolve(value) {
if (this.status === 'pending') {
this.value = value
if (value instanceof P) {
value.then(value => {
this.value = value
})
}
this.status = 'fulfilled'
setTimeout(() => {
this.resolveList.forEach(resolve => {
resolve(this.value)
this.resolveList.shift()
})
}, 0)
}
}
_reject(value) {
// console.log(value)
if (this.status === 'pending') {
this.status = 'rejected'
this.value = value
this.rejectList.forEach(reject => {
reject(this.value)
this.rejectList.shift()
})
}
}
then(resolveFn, rejectFn) {
resolveFn = typeof resolveFn === 'function' ? resolveFn : value => value
rejectFn = typeof rejectFn === 'function' ? rejectFn : value => value
if (this.status === 'fulfilled') {
return new P((resolve, reject) => {
const result = resolveFn(this.value)
if (result instanceof P) result.then(resolve, reject)
resolve(result)
})
}
if (this.status === 'rejected') {
return new P((resolve, reject) => {
const result = rejectFn(this.value)
if (result instanceof P) result.then(resolve, reject)
reject(result)
})
}
if (this.status === 'pending') {
return new P((resolve, reject) => {
this.resolveList.push(() => {
try {
const result = resolveFn(this.value)
resolve(result)
} catch (e) {
reject(e)
}
})
this.rejectList.push(() => {
try {
const result = rejectFn(this.value)
resolve(result)
} catch (e) {
reject(e)
}
})
})
}
}
static resolve(value) {
if (value instanceof P) return value
return new P(resolve => resolve(value))
}
static reject(value) {
return new P((resolve, reject) => reject(value))
}
catch(rejectFn) {
return this.then(undefined, rejectFn)
}
}
new P((resolve, reject) => {
setTimeout(() => reject('init'), 1000)
})
.then(data => {
console.log(data)
return 'first'
})
.then(data => {
console.log(data)
return 'second'
})
.then(data => {
console.log(data)
})```