const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
function Promise(executor) {
const self = this
self.status = PENDING
self.onFulfilled = []
self.onRejected = []
function resolve(value) {
if (self.status === PENDING) {
self.status = FULFILLED
self.value = value
self.onFulfilled.forEach((fn) => fn())
}
}
function reject(value) {
if (self.status === PENDING) {
self.status = REJECTED
self.value = value
self.onRejected.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
Promise.prototype.then = function (onFulfilled, onRejected) {
typeof onFulfilled === 'function' ? onFulfilled : value => value
typeof onRejected === 'function' ? onRejected : value => value
const self = this
let promise2 = new Promise((resolve, reject) => {
if (self.status === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfilled(self.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
})
} else if (self.status === REJECTED) {
setTimeout(() => {
try {
const x = reject(self.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
})
} else if (self.status === PENDING) {
self.onFulfilled.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(self.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
});
})
self.onRejected.push(() => {
setTimeout(() => {
try {
const x = onRejected(self.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
});
})
}
})
return promise2
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
reject(new TypeError('Chaining cycle'));
}
if (x && typeof x === 'object' || typeof x === 'function') {
let used;
try {
let then = x.then
if (typeof then === 'function') {
then.call(x, (y) => {
if (used) return;
used = true
resolvePromise(promise2, y, resolve, reject)
}, (r) => {
if (used) return;
used = true
reject(r)
})
} else {
if (used) return;
used = true;
resolve(x)
}
} catch (error) {
if (used) return;
used = true;
reject(error)
}
} else {
resolve(x)
}
}
new Promise((resolve, reject) => {
resolve(1)
reject(2)
resolve(new Promise((resolve) => resolve(123)))
}).then((r) => console.log(r, 123456), (e) => console.log(e, 123))