实现Promise
参考:
手写 Promise 教程
/**
* 自己实现一个 promise
* Promise
*/
const STATUS = {
PENDING: 1,
FULFILLED: 2,
REJECT: 3
}
class PPromise {
constructor(executor) {
this.status = STATUS.PENDING
this.value = undefined
this.error = undefined
this.onRejectedCallbacks = []
this.onFulfilledCallbacks = []
this.resolve = this.resolve.bind(this)
this.reject = this.reject.bind(this)
this.then = this.then.bind(this)
this.resolvePromise = this.resolvePromise.bind(this)
try {
executor(this.resolve, this.reject)
} catch (err) {
this.reject(err)
}
}
resolve(value) {
if (this.status === STATUS.PENDING) {
this.value = value
this.status = STATUS.FULFILLED
this.onFulfilledCallbacks.forEach(fn => fn())
}
}
reject(error) {
if (this.status === STATUS.REJECT) {
this.error = error
this.status = STATUS.REJECT
this.onRejectedCallbacks.forEach(fn => fn())
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
onRejected = typeof onRejected === 'function' ? onRejected : e => { throw e }
let p2 = new PPromise((resolve, reject) => {
if (this.status === STATUS.FULFILLED) {
setTimeout(() => {
let x = onFulfilled(this.value)
this.resolvePromise(p2, x, resolve, reject)
}, 10);
}
if (this.status === STATUS.REJECT) {
setTimeout(() => {
let x = onRejected(this.error)
this.resolvePromise(p2, x, resolve, reject)
}, 10)
}
if (this.status === STATUS.PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
let x = onFulfilled(this.value)
this.resolvePromise(p2, x, resolve, reject)
}, 10)
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
let x = onRejected(this.error)
this.resolvePromise(p2, x, resolve, reject)
}, 10)
})
}
})
return p2
}
resolvePromise(p2, x, resolve, reject) {
if (x === p2) {
// 存在循环引用
return reject(new TypeError('Changing cycle detected for promise.'))
}
let called
if (x != null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then
if (typeof then === 'function') {
then.call(x, y => {
if (called) return
called = true
this.resolvePromise(p2, y, resolve, reject)
}, err => {
if (called) return
called = true
reject(err)
})
} else {
resolve(x)
}
} catch (e) {
if (called) return
called = true
reject(e)
}
} else {
resolve(x)
}
}
}
setTimeout(() => {
console.log('5')
}, 10)
console.log('1')
var p = new PPromise((resolve, reject) => {
console.log('2')
resolve('')
}).then(res => {
console.log('3')
return new PPromise((resolve, rej) => {
console.log('6')
resolve()
})
})
console.log('p: ', p)
p.then(v => {
console.log('7')
})
console.log('4')
注意:代码实现中使用了settimeout 来模拟js 事件循环中的微任务。并非真正实现 Promise
至此,结束。