前言
前一章讲到通过订阅-发布模式,解决了resolve被setTimeout包裹,导致最终结果出不来的bug。但是,原生的promise还有一个很重要的特性,就是可以进行链式调用,then方法的执行结果也是一个promise对象。下面进入本章的正题。
前一章链接:https://blog.csdn.net/weixin_42344533/article/details/117622308
后一章链接:https://blog.csdn.net/weixin_42344533/article/details/117636782
过程
1、上一个版本实现的promise并不能进行链式调用,因为then没有返回promise对象,所以会报错。
2、版本3中实现了then方法的链式调用,效果图如下。
3、 版本3的then方法链式调用实现,主要是对then方法的返回值进行包装(promise包装)+递归加锁的方式实现。所以接下来,就对版本二的then方法进行改造。
4、全局handlePromise方法实现,主要通过递归加锁方式。
总结
then方法的链式调用,主要实现思路有两个点,一个是对then方法的返回值进行promise对象包装,另一个是对上一个then方法的返回值进行递归加锁处理。
实现源码myPromise.js:
const RESOLVE = 'resolved'
const REJECT = 'rejected'
const PENDING = 'pending'
const handlePromise = (result, newPromise, resolve, reject) => {
if (result === newPromise) {
throw new Error('can not return oneself')
}
if ((typeof result === "object" && result != null) || typeof result === "function") {
let lock = false
const then = result.then
if (typeof then === "function") {
then.call(
result,
r => {
if (lock) return
handlePromise(r, newPromise, resolve, reject)
lock = true
},
e => {
if (lock) return
reject(e)
lock = true
}
)
} else {
resolve(result)
}
} else {
resolve(result)
}
}
function selfPromise(exe) {
this.status = PENDING
this.result = undefined
this.reason = undefined
this.resolveAsyList = []
this.rejectAsyList = []
this.init = (exe) => {
const resolve = (result) => {
if (this.status === PENDING) {
this.result = result
this.status = RESOLVE
this.resolveAsyList.map(resolveAsy => {
resolveAsy()
})
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.reason = reason
this.status = REJECT
this.rejectAsyList.map(rejectAsy => {
rejectAsy()
})
}
}
try {
exe(resolve, reject);
} catch (error) {
reject(error)
}
}
this.then = (onResolve, onReject) => {
const newPromise = new selfPromise((resolve, reject) => {
if (this.status === RESOLVE) {
setTimeout(() => {
const result = onResolve(this.result)
handlePromise(result, newPromise, resolve, reject)
}, 0)
}
if (this.status === REJECT) {
setTimeout(() => {
const result = onReject(this.reason)
handlePromise(result, newPromise, resolve, reject)
}, 0)
}
if (this.status === PENDING) {
this.resolveAsyList.push(() => {
const result = onResolve(this.result)
handlePromise(result, newPromise, resolve, reject)
})
this.rejectAsyList.push(() => {
const result = onReject(this.reason)
handlePromise(result, newPromise, resolve, reject)
})
}
})
return newPromise
}
this.init(exe)
}
module.exports = selfPromise
测试实例test.js:
const myPromise = require('./myPromise_v3')
var test = new myPromise((resolve,reject)=>{
setTimeout(()=>{
resolve("这是手动实现的promise")
},1000)
})
test.then(res=>{
console.log(res)
return "这是版本3的then链式调用返回1"
}).then(res=>{
console.log(res)
return "这是版本3的then链式调用返回2"
}).then(res=>{
console.log(res)
})
console.log("同步代码")
下一章将在版本3的基础上实现原生promise的catch的方法,同时对整个promise对象进行异常处理的优化。
后一章链接:https://blog.csdn.net/weixin_42344533/article/details/117636782