如果你打算手动实现一个promise,你可能需要先问问自己,promise是什么?你平常最常见的promise是怎么样用的?
new Promise((resolve,reject)=>{
resolve(2)
}).then(val=>{
console.log(val)
})
如果你了解事件循环,你就知道,promise里面的回调函数是在立即执行的,而then中的回调任务是会被推入异步微队列中等待执行的。
让我们先来捋捋这个Promise到底是个什么?
Promise是异步函数的一种写法,通过new Promise 创建一个promise对象。promise一种有三种状态:
- pending
- fulfilled
- rejected
初始时,状态都是pending,如果调用了resolve函数,那么这个promise的状态就会变成 fulfilled, 状态一经变更,就再也不能改变了。同样,如果调用了reject函数,promise的状态就会由pending变为rejected. 通过以上的这些信息,我们先来实现一部分Promise的功能。
class Promise{
constructor(executor){
this.state = 'pending'
this.value = undefined
this.reason = undefined
let resolve = value=>{
if(this.state === 'pending'){
this.value = value
this.state = 'fulfilled'
}
}
let reject = reason=>{
if(this.state === 'pending'){
this.reason = reason
this.state = 'rejected'
}
}
try{
executor(resolve,reject) // 立即执行的,执行出错的话,reject
}catch(err){
reject(err)
}
}
then(onFulfilled,onRejected){
if(this.state === 'fulfilled'){
onFulfilled(this.value)
}
if(this.state === 'rejected'){
onRejected(this.reason)
}
}
}
如果我们在setTimeout的回调函数里调用resolve呢?
这时候还使用上述我们自己写的Promise就打印不出来4了,这是为什么呢?
这是因为,在执行executor时,遇到了setTimeout,等待400s后将它的回调()=>{resolve(4)} 推入到异步宏队列中等待空闲执行。接着将.then中的回调推入异步微队列中等待空闲执行。这时候主执行栈空闲, 它会先取出微队列的回调函数执行,执行时,由于this.state还是pending,因此啥也没打印,接着再取出宏任务,resolve(4) 。结果就是啥也没打印。因此我们优化一下代码。
class Promise{
constructor(executor){
this.state = 'pending'
this.value = undefined
this.reason = undefined
this.fulfilledCallbacks = []
this.rejectedCallbacks = []
let resolve = value=>{
if(this.state === 'pending'){
this.value = value
this.state = 'fulfilled'
this.fulfilledCallbacks.forEach(callback =>{
callback(value)
})
}
}
let reject = reason=>{
if(this.state === 'pending'){
this.reason = reason
this.state = 'rejected'
this.rejectedCallbacks.forEach(callback =>{
callback(reason)
})
}
}
try{
executor(resolve,reject)
}catch(err){
reject(err)
}
}
then(onFulfilled,onRejected){
if(this.state === 'pending'){
this.fulfilledCallbacks.push(onFulfilled)
this.rejectedCallbacks.push(onRejected)
}
if(this.state === 'fulfilled'){
onFulfilled(this.value)
}
if(this.state === 'rejected'){
onRejected(this.reason)
}
}
}
ok~ 测试了一下没有问题
promise还有很多其他功能,在下篇可以一一挖掘
promise的实现(如何手写一个promise)(下)