本文正在参加「金石计划」
前言:简单的实现一下Promise的核心。
初始结构:
在 new Promise() 实例的时候要传入一个函数作为参数,并且该函数参数会被自动执行;同时我们也需要向这个函数参数传入它自己的参数resolve与 reject;在原生的Promise里面,resolve与reject都是以函数的形式执行的,所以我们可以使用类方法的形式来创建这两个函数。
class Pro{
static PENDING='pending';static FULFILLED='fulfiled';static REJECTEd='rejected' // 定义promise的三种状态
constructor(fn){
this.status=Pro.PENDING // 初始化promise对象的状态
fn(this.resolve,this.reject) // promise对象中传入的函数
}
resolve(){};
reject(){};
}
resolve与reject 函数
Promise对象的resolve函数与reject函数都是取决于Promise对象本身的状态:
- pending:待定
- fulfilled:成功
- rejected:拒绝
并且resolve函数的功能是将Promise对象的状态从 pending 变成 fulfilled 状态;而reject函数的功能是将Promise对象的状态从 pending 变成 rejected 状态,同时这两个函数也接收参数,。所以完善这两个函数的功能:
class Pro {
static PENDING = 'pending'; static FULFILLED = 'fulfiled'; static REJECTED = 'rejected' // 定义promise的三种状态
constructor(fn) {
this.status = Pro.PENDING // 初始化promise对象的状态
this.result = null // resolve与reject函数的参数
fn(this.resolve.bind(this), this.reject.bind(this)) // 这里绑定this 因为在new出新实例之后再到外部环境执行这两个方法 this 丢失
}
resolve(result) {
if (this.status === Pro.PENDING) {
this.status = Pro.FULFILLED
this.result=result
}
};
reject(result) {
if (this.status === Pro.PENDING) {
this.status = Pro.REJECTED
this.result=result
}
};
}
then方法
Promise.then()方法可接收两个参数,第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数,它们都是可选的,并且该方法只会执行某一个回调函数。当然在原生Promise的then方法里面如果传入的不是函数:如果忽略针对某个状态的回调函数参数,或者提供非函数 (nonfunction) 参数,那么 then 方法将会丢失关于该状态的回调函数信息,但是并不会产生错误。所以需要再判断。
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => { } // 判断传入的是否为函数
onRejected = typeof onRejected === 'function' ? onFulfilled : () => { }
if (this.status === Pro.FULFILLED) {
onFulfilled(this.result)
}
if (this.status === Pro.REJECTED) {
onRejected(this.result)
}
}
异步
此时的Promise还不能实现异步的效果:
let p=new Pro((resolve,reject)=>{
console.log(2);
resolve('yes')
})
p.then(res=>{
console.log(res);
})
console.log(3);
//1
//2
//yes
//3
此时的执行结果不会像正常的Promise一样先执行3 再执行.then 异步方法。所以我们可以在then方法里面通过设置setTimeout将其转化成异步仍任务。
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => { }
onRejected = typeof onRejected === 'function' ? onFulfilled : () => { }
if (this.status === Pro.FULFILLED) {
setTimeout(()=>{
onFulfilled(this.result)
})
}
if (this.status === Pro.REJECTED) {
setTimeout(()=>{
onRejected(this.result)
})
}
}
但是此时仍然存在着一个问题:
console.log(1);
let p=new Pro((resolve,reject)=>{
console.log(2);
setTimeout(()=>{
resolve('yes')
console.log(4);
})
})
p.then(res=>{
console.log(res);
},
res=>{console.log(res);})
console.log(3);
//1
//2
//3
//4
如果在Promsie里面添加setTimeout方法,那么此时resolve方法就不会被执行。那么导致这个结果产生的原因是什么?看看代码:执行了 打印 1 2 3 之后,此时轮到处理异步代码,然而此时Promise的状态还是pending,而我们没有处理pending的方法,所以此时resolve/reject方法就不执行。所以我们就要让then里面的函数稍后执行,让resolve执行完成之后再执行then方法。我们可以使用一个数组来保存函数。
class Pro {
static PENDING = 'pending'; static FULFILLED = 'fulfiled'; static REJECTED = 'rejected' // 定义promise的三种状态
constructor(fn) {
this.status = Pro.PENDING // 初始化promise对象的状态
this.resolveCallbacks = [] // 保存待执行函数
this.rejectCallbacks = []
this.result = null // resolve与reject函数的参数
try {
fn(this.resolve.bind(this), this.reject.bind(this)) // 这里绑定this 因为在new出新实例之后再到外部环境执行这两个方法 this 丢失
} catch (error) {
this.reject(error)
}
}
resolve(result) {
setTimeout(() => {
if (this.status === Pro.PENDING) {
this.status = Pro.FULFILLED
this.result = result
this.resolveCallbacks.forEach(callback => { // 遍历数组如果有待执行函数就执行
callback(result)
})
}
})
};
reject(result) {
setTimeout(() => {
if (this.status === Pro.PENDING) {
this.status = Pro.REJECTED
this.result = result
this.rejectCallbacks.forEach(callback => {
callback(result)
})
}
})
};
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => { }
onRejected = typeof onRejected === 'function' ? onFulfilled : () => { }
if (this.status === Pro.PENDING) { // pending 状态
this.resolveCallbacks.push(onFulfilled)
this.rejectCallbacks.push(onRejected)
}
if (this.status === Pro.FULFILLED) {
setTimeout(() => {
onFulfilled(this.result)
})
}
if (this.status === Pro.REJECTED) {
setTimeout(() => {
onRejected(this.result)
})
}
}
}
链式
实现链式直接在then方法里面返回出一个新的Promise对象即可。
class Pro {
static PENDING = 'pending'; static FULFILLED = 'fulfiled'; static REJECTED = 'rejected' // 定义promise的三种状态
constructor(fn) {
this.status = Pro.PENDING // 初始化promise对象的状态
this.resolveCallbacks = []
this.rejectCallbacks = []
this.result = null // resolve与reject函数的参数
try {
fn(this.resolve.bind(this), this.reject.bind(this)) // 这里绑定this 因为在new出新实例之后再到外部环境执行这两个方法 this 丢失
} catch (error) {
this.reject(error)
}
}
resolve(result) {
setTimeout(() => {
if (this.status === Pro.PENDING) {
this.status = Pro.FULFILLED
this.result = result
this.resolveCallbacks.forEach(callback => {
callback(result)
})
}
})
};
reject(result) {
setTimeout(() => {
if (this.status === Pro.PENDING) {
this.status = Pro.REJECTED
this.result = result
this.rejectCallbacks.forEach(callback => {
callback(result)
})
}
})
};
then(onFulfilled, onRejected) {
return new Pro((resolve, reject) => {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => { }
onRejected = typeof onRejected === 'function' ? onFulfilled : () => { }
if (this.status === Pro.PENDING) {
this.resolveCallbacks.push(onFulfilled)
this.rejectCallbacks.push(onRejected)
}
if (this.status === Pro.FULFILLED) {
setTimeout(() => {
onFulfilled(this.result)
})
}
if (this.status === Pro.REJECTED) {
setTimeout(() => {
onRejected(this.result)
})
}
})
}
}
以上就简单的梳理了一下promise比较核心的一些功能。