const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECT = 'reject'
class MyPromise {
constructor(exectur) {
this.status = PENDING
this.value = ''
this.reason = ''
this.onFulfilledCb = []
this.onRejectedCb = []
try {
exectur(this.resolve(), this.reject())
} catch (err) {
this.reject(err)
}
}
resolve = (value) => {
if (this.status === PENDING) {
this.status === FULFILLED
this.value = value
this.onFulfilledCb.forEach(fn => fn())
}
}
reject = (reason) => {
if (this.status === PENDING) {
this.status === REJECT
this.reason = reason
this.onRejectedCb.forEach(fn => fn())
}
}
then = (onFulfilled, onRejected) => {
onFulfilled = typeof onFulfilled == 'function' ? onFulfilled : value => value
onRejected = typeof onRejected == 'function' ? onRejected : (err) => { throw err };
let promise2
if (this.status === PENDING) {
promise2 = new MyPromise((resolve, reject) => {
this.onFulfilledCb.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(this, x, resolve, reject)
} catch (err) {
reject(err)
}
})
})
this.onRejectedCb.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(this, x, resolve, reject)
} catch (err) {
reject(err)
}
})
})
})
}
if (this.status === FULFILLED) {
promise2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(this, x, resolve, reject)
} catch (err) {
reject(err)
}
})
})
}
if (this.status === REJECT) {
promise2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(this, x, resolve, reject)
} catch (err) {
reject(err)
}
})
})
}
return promise2
}
catch = callback => {
return this.then(null, callback)
}
all = list => {
return new MyPromise((resolve, reject) => {
let count = 0
let result = []
let len = list.length
if (len === 0) {
return resolve(result)
}
list.forEach((item, index) => {
MyPromise.resolve(item).then((value) => {
count++
result.push(value)
if (count === len) {
return resolve(result)
}
}, reason => {
reject(reason)
})
})
})
}
any = list => {
return new MyPromise((resolve, reject) => {
let count = 0
let result = []
let len = list.length
if (len === 0) return resolve(result)
list.forEach((item, index) => {
MyPromise.resolve(item).then(value => {
resolve(value)
}, reason => {
count++
result.push(reason)
if (count === len) {
reject(result)
}
})
})
})
}
race = list => {
return new MyPromise((resolve, reject) => {
let len = list.length
list.forEach(item => {
MyPromise.resolve(item).then(value => {
resolve(value)
}, reason => {
reject(reason)
})
})
})
}
finally = fn => {
return this.then(value => {
return MyPromise.resolve(fn()).then(() => {
return value
})
}, reason => {
return MyPromise.resolve(fn()).then(() => {
throw reason
})
})
}
}
function resolvePromise(promise, x, resolve, rejcet) {
if (promise === x) {
return rejcet(new TypeError('cycle...'))
}
let called = false
if (['null', 'function'].includes(typeof x) && typeof x !== null) {
try {
let then = x.then
if (typeof then === 'funciton') {
then.call(x, y => {
if (called) return
called = true
resolvePromise(promise, y, resolve, rejcet)
}, error => {
if (called) return
called = true
reject(error)
})
} else {
resolve(x)
}
} catch (err) {
if (called) return
called = true
reject(err)
}
} else {
resolve(x)
}
}