// 实现ES6的promise功能
// states
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
// 用ES6的类定义一个构造函数
class myPromise {
// 私有属性#
#state = PENDING
#result = undefined
#handler = undefined // 记录then方法传入的方法
constructor(executor) {
const resolve = (data) => {
this.#changeState(FULFILLED, data)
}
const reject = (reason) => {
this.#changeState(REJECTED, reason)
}
try {
// 只能捕获同步错误,异步报错无法捕获,状态会一直停留在'pending'
executor(resolve, reject)
}
catch (err) {
reject(err)
}
}
#changeState(state, result) {
if (this.#state !== PENDING) return
this.#state = state
this.#result = result
this.#run
}
// 判断是否符合promise A+规范:一个对象或函数,且具有then方法就符合
#isPromiseLike(value) {
if (value !== null && (typeof value === 'object' || typeof value === 'function')) {
return typeof value.then === 'function'
}
return false
}
// 在微队列中执行回调函数
#runMicroTask(func) {
// node环境中
if (typeof process === 'object' && typeof process.nextTick === 'function') {
process.nextTick(func)
}
// 浏览器环境,使用MutationObserver观察一个文本节点,当其变化,就会把函数放入微队列中执行
else if (typeof MutationObserver === 'function') {
const ob = new MutationObserver(func)
const textNode = document.createTextNode('1')
ob.observe(textNode, {
characterData: true
})
textNode.data = '2'
}
// 如果当前浏览器环境不支持MutationObserver,降级为setTimeout
else {
setTimeout(func, 0)
}
}
#runOne(callback, resolve, reject) {
this.#runMicroTask(_ => {
if (typeof callback !== 'function') { // 传入的回调函数不为函数,则根据当前的promise状态返回
const settled = this.#state === FULFILLED ? resolve : reject
settled(this.#result)
return
}
try {
const data = callback(this.#result)
if (this.#isPromiseLike(data)) { // 传入的回调函数为函数,执行后的返回值为promise,则继续链式调用then方法
data.then(resolve, reject)
} else {
resolve(data) // 执行后不为promise,则直接返回
}
} catch (err) {
reject(err)
}
})
}
#run() {
if (this.#state !== PENDING) return
while (this.#handler.length) {
const { onFulfilled, onRejected, resolve, reject } = this.#handler.shift()
if (this.#state === FULFILLED) {
this.#runOne(onFulfilled, resolve, reject)
} else if (this.#state === REJECTED) {
this.#runOne(onRejected, resolve, reject)
} else {
}
}
}
then(onFulfilled, onRejected) {
return new myPromise((resolve, reject) => {
// then方法可以会执行多次,把每次的回调函数等用数组储存起来
this.#handler.push({
onFulfilled,
onRejected,
resolve,
reject
})
this.#run()
})
}
// catch方法返回失败回调
catch(onRejected) {
return this.then(undefined, onRejected)
}
// finally方法,对于当前promise进行不判断状态的回调
finally(onFinally) {
return this.then(data => {
onFinally()
return data // finally状态透明,成功和失败都返回promise的状态
}, err => {
onFinally()
throw err
})
}
// resolve方法返回一个promise,如果传入的值为promise实例,即返回传入值
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
}
// reject方法返回一个失败的promise,并把传入值作为失败原因抛出
static reject(reason) {
return new myPromise((resolve, reject) => {
reject(reason)
})
}
}
// 测试一下:
const mp1 = new myPromise((resolve, reject) => {
setTimeout(_=>{
resolve(1)
}, 1000)
})
const mp2 = new myPromise((resolve, reject) => {
setTimeout(_=>{
reject(2)
}, 1000)
})
console.log(mp1) // myPromise {#state: 'fulfilled', #result: 1, #handler: undefined}
console.log(mp2) // myPromise {#state: 'rejected', #result: 2, #handler: undefined}
03-12
216
06-16
3384