const PENDING = 'PENDGING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'
class MyPromise {
constructor (executor) {
try {
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}
status = PENDING
value = undefined
reason = undefined
successCallback = []
failCallback = []
resolve = value => {
if (this.status !== PENDING) return
this.status = FULFILLED
this.value = value
while (this.successCallback.length) this.successCallback.shift()()
}
reject = reason => {
if (this.status !== PENDING) return
this.status = REJECTED
this.reason = reason
while (this.failCallback.length) this.failCallback.shift()()
}
then (successCallback, failCallback) {
successCallback = successCallback ? successCallback : value => value
failCallback = failCallback ? failCallback : reason => { throw reason }
const promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
const x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
const x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
} else {
this.successCallback.push(() => {
setTimeout(() => {
try {
const x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
this.failCallback.push(() => {
setTimeout(() => {
try {
const x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
}
})
return promise2
}
finally (callback) {
return this.then(value => {
return MyPromise.resolve(callback()).then(() => value)
}, reason => {
return MyPromise.resolve(callback()).then(() => { throw reason })
})
}
catch (failCallback) {
return this.then(undefined, failCallback)
}
static resolve (value) {
if (value instanceof MyPromise) {
return value
} else {
return new MyPromise((resolve, reject) => {
resolve(value)
})
}
}
static all (arr) {
const result = []
let index = 0
return new MyPromise((resolve, reject) => {
function addData (key, value) {
result[key] = value
index++
if (index === arr.length) {
resolve(result)
}
}
for (let i = 0; i < arr.length; i++) {
const current = arr[i]
if (current instanceof MyPromise) {
current.then(value => addData(i, value), reason => reject(reason))
} else {
addData(i, arr[i])
}
}
})
}
static race (arr) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < arr.length; i++) {
const current = arr[i]
if (current instanceof MyPromise) {
current.then(value => {
resolve(value)
}, reason => {
reject(reason)
})
} else {
resolve(current)
}
}
})
}
}
function resolvePromise (promise, x, resolve, reject) {
if (promise === x) {
return reject(new TypeError('chaining cycle detected for promise #<Promise>'))
}
if (x instanceof MyPromise) {
x.then(resolve, reject)
} else {
resolve(x)
}
}
const t = function () {
setTimeout(() => { console.log('定时器执行') }, 1000)
}
const p = function () {
return new MyPromise((resolve, reject) => {
console.log('promise 执行器执行')
resolve('promise resolve 执行')
})
}
MyPromise.race([t(), p(), 4]).then(r => console.log(r))
Promise.race([t(), p(), 4]).then(r => console.log(r))
console.log(123)