实现目标
- 定义promise构造函数
- 实现then方法
- then方法的链式调用
- 实现catch方法
- 实现finally方法
- 实现resolve静态方法
- 实现all静态方法
代码
class MPromise {
constructor(handler) {
// 保存promise的状态
this.status = 'PENDING'
// 将then()中resolve方法加入到队列中,当执行promise状态变为“成功态”后调用
this.resolveHandlers = []
this.rejectHandlers = []
// 保存finally()回调函数,当promise状态改变后调用
this.finallyHandlers = []
// 将_resolve()中的this指向绑定到当前实例对象
handler(this._resolve.bind(this), this._reject.bind(this))
}
_resolve(val) {
// 状态改变后,不能再执行
if (this.status != 'PENDING') return
this.status = 'FULFILLED'
this._observer(() => {
// 状态改变后,从事件队列(FIFO)中获取循环获取事件执行
let handler;
while (handler = this.resolveHandlers.shift()) {
handler(val)
}
while (handler = this.finallyHandlers.shift()) {
handler(val)
}
})
}
_reject(val) {
if (this.status != 'PENDING') return
this.status = 'REJECTED'
this._observer(() => {
let handler;
while (handler = this.rejectHandlers.shift()) {
handler(val)
}
while (handler = this.finallyHandlers.shift()) {
handler(val)
}
})
}
// 将事件对象放入到MutationObserver微任务中,目的是保证then()中事件先于setTimeout等宏任务执行
_observer(callback) {
let observer = new MutationObserver(() => {
callback()
observer.disconnect()
})
observer.observe(document.body, {
attributes: true
})
document.body.setAttribute('mb', Math.random())
}
then(resolveCb, rejectCb) {
return new MPromise((resolve, reject) => {
if (resolveCb && typeof resolveCb == "function") {
// 将resolve事件放入到resolve队列中,目的是保证promise状态改变为“成功态”后,再执行
this.resolveHandlers.push(val => {
// 链式调用时,获取resolve事件返回值,并传入到下次then()中
val = resolveCb(val)
if (val && val instanceof MPromise) {
return val.then(resolve, reject)
}
resolve(val)
})
}
if (rejectCb && typeof rejectCb == "function") {
this.rejectHandlers.push(val => {
val = rejectCb(val)
if (val && val instanceof MPromise) {
return val.then(resolve, reject)
}
reject(val)
})
}
})
}
// 类似于then()中的第二个参数
catch(cb) {
return this.then(null, cb)
}
// 不能立即执行,放入事件队列中,等待promise状态改变后再执行
finally(cb) {
this.finallyHandlers.push(cb)
}
static resolve(val) {
return new MPromise(resolve => {
resolve(val)
})
}
static all(it) {
let len = it.length
return new MPromise(resolve => {
let vals = []
let n = 0
for (let i = 0; i < len; i++) {
it[i].then(val => {
// 保证返回数组中顺序和promise一致
vals[i] = val
n++
// 当数组中promise对象全部执行完成后,再调用resolve()
if (n == len) {
resolve(vals)
}
})
}
})
}
}
测试
实现promise构造函数
/**
* 1. 构造函数内部代码立即执行
* 2. 构造函数一个方法,方法中接受两个函数作为参数
* - resolve:将promise状态变为“成功态”
* - reject:将promise状态变为“失败态”
* 3. promise状态一旦改变就不能再次更改
*/
let p = new MPromise((resolve, reject) => {
console.log("promise")
resolve(100)
// reject('error')
})
实现then方法
/**
* 1. 接受两个回调函数作为参数
* - 第一个参数:promise状态变为“成功”时调用
* - 第二个参数:promise状态变为“失败”时调用
* 2. 回调函数中可接受调用resolve()、reject()方法时,传递的参数
* 3. then()中执行顺序先于setTimeout异步函数
*/
console.log('1111')
setTimeout(() => {
console.log("外部setTimeout执行")
})
let p = new MPromise((resolve, reject) => {
console.log("promise")
resolve(100)
})
p.then(res => {
console.log('then方法中的返回值:', res)
}, err => {
console.log('then方法中返回的错误:', err)
})
then方法的链式调用
/**
* 1. then方法返回一个promise对象,可实现方法的链式调用
* 2. then方法接受参数函数中,可返回值/Promise对象作为再次then()回调函数的参数
* - 返回值:封装为promise对象返回
* - 返回promise对象:调用then()后返回
*
*/
let p = new MPromise((resolve, reject) => {
console.log("promise")
resolve(100)
})
p.then(res => {
console.log('then方法中的返回值:', res)
// return 200
return new MPromise((resolve, reject) => {
resolve(200)
})
}).then(res => {
console.log("第二次then方法中的返回值:", res)
})
实现catch方法
/**
* 1. 只实现了捕获调用reject()的错误,未实现new Error()中的错误
* 2. 回调函数中可接受调用reject()方法时,传递的参数
*/
let p = new MPromise((resolve, reject) => {
console.log("promise")
resolve(100)
})
p.then(res => {
console.log('then方法中的返回值:', res)
return new MPromise((resolve, reject) => {
reject('error')
})
}).catch(err => {
console.log('catch中捕获的错误:', err)
})
实现finally方法
/**
* 1. 接受回调函数作为参数,promise状态改变后执行
*/
let p = new MPromise((resolve, reject) => {
console.log("promise")
resolve(100)
})
p.then(res => {
console.log('then方法中的返回值:', res)
return new MPromise((resolve, reject) => {
reject('error')
})
}).catch(err => {
console.log('catch中捕获的错误:', err)
}).finally(() => {
console.log('执行finally')
})
实现resolve静态方法
/**
* 1. 返回一个“成功态”的promise对象
*/
let p = MPromise.resolve(100)
console.log(p)
实现all静态方法
/**
* 1. 接受一个promise数组
* 2. 数组中promise全部调用完成后,返回一个包含promise数组结果的promise对象
*/
let p1 = new MPromise((resolve, reject) => {
setTimeout(() => {
resolve(100)
}, 500)
})
let p2 = new MPromise((resolve, reject) => {
setTimeout(() => {
resolve(200)
}, 1000)
})
let p3 = new MPromise((resolve, reject) => {
setTimeout(() => {
resolve(300)
}, 100)
})
MPromise.all([p1, p2, p3]).then(vals => {
console.log(vals)
})