先说一下大致的思路,可能并不是按照这么个顺序,我也是模仿Promise的基本使用,就想起来啥总结啥,我觉得应是把 Promise 核心的部分写出来了。
?1. 创建MyPromise类
?2. 实例化时传入一个函数fn,并立即执行
?3. fn有两个形参(resolve和reject),并且都是函数
?4. 声明Promise的三个状态分别是 pending、fulfilled、rejected,并在实例化的时候赋予初始pending状态
?5. 调用resolve和reject的时候 改变其状态,调用then方法,并将数据传递过去。实例化时给Promise一个初始数据result = null
?6. then方法中的形参都是异步调用,resolve和reject也都是最后执行,所以采用 setTimeout
?7. 示例化的时候 如果出现错误或抛出异常,应该进行对异常捕获 调用reject方法,所以实例化立即执行的时候 采用 try catch
?8. then 方法的两个形参都必须是函数,如果传入的不是函数咱们就给其一个空函数
?9. 如果resolve也是个异步,这样的话,执行then方法的时候,判断状态还是pending,这时候就要分别向两个数组中 暂存then中两个的方法,在调用resolve的时候再去遍历调用。就是个发布订阅
10. then方法可以链式调用,所以我们在then方法中再返回一个手写的 MyPromise 即可
下面是代码:
class MyPromise {
static PENDING = 'pending'
static FULFILLED = 'fulfilled'
static REJECTED = 'rejected'
constructor(fn) {
this.status = MyPromise.PENDING
this.result = null
this.resolveCallbacks = []
this.rejectCallbacks = []
try {
fn(this.resolve.bind(this), this.reject.bind(this))
}catch(err) {
this.reject(err)
}
}
resolve(data) {
setTimeout(() => {
if(this.status == MyPromise.PENDING) {
this.status = MyPromise.FULFILLED
this.result = data
if(this.resolveCallbacks.length) {
this.resolveCallbacks.forEach(callback => {
callback(data)
})
}
}
})
}
reject(err) {
setTimeout(() => {
if(this.status == MyPromise.PENDING) {
this.status = MyPromise.REJECTED
this.result = err
if(this.rejectCallbacks.length) {
this.rejectCallbacks.forEach(callback => {
callback(err)
})
}
}
})
}
then(ONFULFILLED, ONREJECTED) {
return new MyPromise((resolve, reject) => {
ONFULFILLED = typeof ONFULFILLED === 'function' ? ONFULFILLED : () => {}
ONREJECTED = typeof ONREJECTED === 'function' ? ONREJECTED : () => {}
if(this.status == MyPromise.PENDING) {
this.resolveCallbacks.push(ONFULFILLED)
this.rejectCallbacks.push(ONREJECTED)
}
if(this.status == MyPromise.FULFILLED) {
setTimeout(() => {
ONFULFILLED(this.result)
})
}
if(this.status == MyPromise.REJECTED) {
setTimeout(() => {
ONREJECTED(this.result)
})
}
})
}
}
简单测试?
console.log('111111')
new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('resolve')
// reject('reject')
console.log('哈哈哈')
})
}).then(data => {
console.log(data)
}, err => {
console.log(err)
})
|