前言:在此之前,我们以及陆续封装好了Promise、then、all,这些方法,并且以及讲解了其中的机制,和封装的过程,现在,我们就把剩下的较为简单的方法过一遍。
1. race()
这个方法类似于all方法,传入的参数也是一个有Promise组成的数组,但是它的结果分析起来就相对简单很多,不用过多的考虑,其返回的值也是一个Promise对象,既然返回的是一个Promise对象,那么就存在链式调用,那么就需要进行二次封装,内部就需要调用then方法,它的结果机制是这样的:返回的是一个Promise对象,其对象的值,为传入的Promises中第一个Promise执行后的值,其状态也为该Promise的状态。是不是比all方法简单多了,这样的话我们封装的到结果就为:
// 添加 race 方法
Promise.race = function(promises) {
return new Promise((resolve , reject) => {
for(let i = 0 ; i < promises.length ; i++) {
promises[i].then(v => {
resolve(v)
} , r => {
reject(r)
})
}
})
}
接下来的两种方法也较为简单(resolve() 、reject() ),但是也关系到一点点关键性问题,类似于之前我们讲解race方法,其实是差不多的。
2. resolve()
该方法的返回值和也是一个Promise对象,其返回的结果需要根据传入的值进行区分
(1):传入的为非Promise对象的值,最终方法返回的结果为一个成功状态的Promise,其值为传入的值
(2):传入的为Promise对象,最终方法返回的结果需根据传入的这个Promise对象的执行结果进行判断,和传入的Promise的执行保持一致,传入的为失败,方法返回的就是失败的Promise,传入的为成功,返回的就是成功的Promise,值都是传入的Promise的值
(3):抛出异常,由then方法捕获
这样我们就得到:
// 添加 resolve 方法
Promise.resolve = function(value) {
return new Promise((resolve , reject) => {
if(value instanceof Promise) {
value.then(v => {
resolve(v)
} , r => {
reject(r)
})
} else {
// 传入的参数不是一个promise对象,直接修改状态为成功,值为传入的值
resolve(value)
}
})
}
3. reject()
这里大家可能会想到和resolve方法一样,其实不然,reject方法因为返回方法虽然也是一个Promise对象,但是他不存在链式调用,所以就不需要二次封装,也自然就不需要做过多的判断:
// 添加 reject 方法
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
以上就是剩下的三种方法的封装了。
接下来我们再次进行一个then方法的小优化,我们先来看看一个场景,现在我们封装的then方法和官方库的区别:
场景:
let p1 = new Promise((resolve , rejeve) => {
resolve("OK")
console.log(111)
})
p1.then(value => {
console.log(222)
},reason => {
})
console.log(333)
官方结果:
我们封装的结果:
结果很明显,这是为什么呢,哎,这就要会到原来的主题,异步调用,我们仔细分析这段代码,官方库中,先执行了Promise里面那段代码,输出了111并且调用了成功的回调对吧,代码往下走,因为是异步调用,所以代码会先走下方同步调用输出333,最后异步执行p1.then()方法执行成功的回调,最后输出222。而我们的呢,并没有进行这个细节的改动,核心的代码是这:
// 判断当前实例对象的Promise状态 依据状态调用相应的函数
if (this.PromiseState === "fulfilled" || this.PromiseState === "resolved") {
callback(onResolved)
}
if (this.PromiseState === "rejected") {
callback(onRejected)
}
我们是直接同步执行的,所以我们得把这段改成异步调用的额,很简单,加一个定时器即可了,就像这样(因为定时器就是异步调用的,我们不需要定义异步调用的时间,为空即可):
// 判断当前实例对象的Promise状态 依据状态调用相应的函数
if (this.PromiseState === "fulfilled" || this.PromiseState === "resolved") {
setTimeout(() => {
callback(onResolved)
})
}
if (this.PromiseState === "rejected") {
setTimeout(() => {
callback(onRejected)
})
}
再次调试看结果:
这样我们就优化好了。
至此,我们的手写Promise的已经完全结束了,之后我会给出一个完整的Promise和类封装的Promise源码,还会列举出一些Promise的关键性问题,也是使用Promise一些的关键问题,封装的过程中也都提到了,之后会做一个汇总,尽请期待