class MyPromise {
value = undefined
successPool = []
failPool = []
status = 'pedding'
constructor(fn) {
try { fn(this.resolve, this.reject) }
catch(e) { this.reject(e) }
}
resolve(value) {
const executeSuccessPool = () => {
let cb
while (cb = this.successPool.shift()) {
cb(this.value)
}
}
const executeFailPool = () => {
let cb
while (cb = this.failPool.shift()) {
cb(this.value)
}
}
if(value instanceof MyPromise) {
value.then(
v => {
this.status = 'success'
this.value = v
executeSuccessPool()
},
err => {
this.status = 'fail'
this.value = err
executeFailPool()
}
)
} else {
this.value = value
this.status = 'success'
executeSuccessPool()
}
}
reject(err) {
this.status = 'fail'
this.value = err
executeFailPool()
}
catch(c) {
this.then(undefined, c)
}
then(scb, fcb) {
return new MyPromise((rel, rej) => {
const resolveCb = () => {
if (!scb || typeof scb !== 'function') {
rel(this.value)
} else {
const val = scb(this.value)
if (val instanceof MyPromise) {
val.then(rel, rej)
} else {
rel(val)
}
}
}
const rejectCb = () => {
if (!fcb || typeof fcb !== 'function') {
rej(this.value)
} else {
const val = fcb(this.value)
if (val instanceof MyPromise) {
val.then(rel, rej)
} else {
rel(val)
}
}
}
if (this.status === 'success') {
resolveCb()
}
if (this.status === 'fail') {
rejectCb()
}
if (this.status === 'pedding') {
this.successPool.push(resolveCb)
this.failPool.push(rejectCb)
}
})
}
_resolve(v) {
if (v instanceof MyPromise) return v
return new MyPromise(rel => rel(v))
}
static all(arr) {
const res = []
let count = 0
return new MyPromise((rel, rej) => {
arr.forEach((i, index) => {
this._resolve(i).then(
v => {
res[index] = v
count++
if (count === arr.length) rel(res)
},
err => {
rej(err)
}
)
})
})
}
static race(arr) {
return new MyPromise((rel, rej) => {
for (const p of arr) {
this._resolve(p).then(
v => {
rel(v)
},
err => {
rej(err)
}
)
}
})
}
}