const PENDING = 'pending'
const FULFILLED = 'fullfilled'
const REJECTED = 'rejected'
class MyPromise {
state = PENDING
result = undefined
handlers = []
constructor(executor) {
const resolve = (data) => {
this.changeState(FULFILLED, data)
}
const reject = (reson) => {
this.changeState(REJECTED, reson)
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
changeState(state, result) {
if (this.state !== PENDING) return
this.state = state
this.result = result
this.run()
}
isPromiseLike = (value) => {
if (value !== null && (typeof value === 'object' || typeof value === 'function')) {
return typeof value.then === 'function'
}
return false
}
runMocroTask = (func) => {
if (typeof process === 'object' && typeof process.nextTick === 'function') {
process.nextTick(func)
} else if (typeof MutationObserver === 'function') {
const ob = new MutationObserver(func)
const textNode = document.createTextNode('1')
ob.observe(textNode, {
characterData: true
})
textNode.data = '2'
} else {
setTimeout(func, 0)
}
}
runOne = (callback, resolve, reject) => {
this.runMocroTask(() => {
// 1、对应回调函数不是一个函数 直接把结果返回
if (typeof callback !== 'function') {
const settled = this.state === FULFILLED ? resolve : reject
settled(this.result)
return
}
// 2、回调函数是一个函数
try {
const data = callback(this.result)
// 3、返回的是不是promise(满足promiseA+规范就行)
if (this.isPromiseLike(data)) {
data.then(resolve, reject)
} else {
resolve(data)
}
} catch (error) {
reject(error)
}
})
}
run() {
if (this.state === PENDING) return
while (this.handlers.length) {
const {
onFulfilled,
onRejected,
reject,
resolve
} = this.handlers.shift()
if (this.state === FULFILLED) {
this.runOne(onFulfilled, resolve, reject)
} else {
this.runOne(onRejected, resolve, reject)
}
}
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
this.handlers.push({
onFulfilled,
onRejected,
resolve,
reject
})
this.run()
})
}
catch (onRejected) {
return this.then(undefined, onRejected)
}
finally(onFinally) {
return this.then((data) => {
onFinally()
return data
}, (err) => {
onFinally()
throw err
})
}
static resolve(value) {
if (value instanceof MyPromise) return value
let _resolve, _reject
const p = new MyPromise((resolve, reject) => {
_resolve = resolve
_reject = reject
})
if (p.isPromiseLike(value)) {
value.then(_resolve, _reject)
} else {
_resolve(value)
}
return p
}
static reject(reson) {
return new Promise((resolve, reject) => {
reject(reson)
})
}
}
// 测试
// function delay(duration = 1000) {
// return new MyPromise((resolve, reject) => {
// setTimeout(resolve, duration)
// })
// }
// async function test() {
// await delay(1000)
// console.log('ok1');
// await delay(1000)
// console.log('ok2');
// }
// test()
// const p = new MyPromise((resolve, reject) => {
// setTimeout(() => {
// resolve(1)
// }, 1000);
// })
// p.then((data) => {
// console.log('ok1', data);
// return new Promise((resolve, reject) => {
// setTimeout(() => {
// resolve(data * 2)
// }, 1000);
// })
// }).then((data) => {
// console.log('ok2', data);
// })
// new MyPromise((resolve, reject) => {
// resolve(123)
// // reject(123)
// }).finally((err) => {
// console.log(err);
// })
// const p1 = new MyPromise((resolve, reject) => {
// resolve(1)
// })
// console.log(MyPromise.resolve(p1) === p1); // true
// MyPromise.resolve(1).then((data) => {
// console.log(data);
// })
MyPromise.reject(1).catch((data) => {
console.log(data);
})