前言
上一章,我们实现了promise的then方法链式调用,本章节就对原型promise的catch方法进行简单的实现,同时对对象进行一个整体的异常处理优化,以提高对象整体的健壮度。
上一章链接:https://blog.csdn.net/weixin_42344533/article/details/117624450
过程
1、promise对象catch方法实现效果图。
2、实现catch原理:其实就是then方法的语法糖,参数,内部实现最终还是利用了then方法。
3、由于本人的疏忽,造成上一个版本存在一个bug,就是后一个then方法会错误地接收前一个then方法返回的err,造成回调混乱。
4、本版本对上一版本的bug进行了修复,对全局的handlePromise方法进行了修改,多传进来当前对象的status状态,通过判断该状态来决定执行resolve方法还是reject方法。
5、该版本还对promise对象内部进行了异常处理的优化,防止外部函数的错误而造成内部函数执行的失败,同时通过reject把异常抛出。
实现源码myPromise_v4.js:
const RESOLVE = 'resolved'
const REJECT = 'rejected'
const PENDING = 'pending'
const handlePromise = (status, 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
try {
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)
}
} catch (error) {
reject(error)
}
} else if (status === RESOLVE) {
resolve(result)
} else {
reject(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.init(exe)
this.then = (onResolve, onReject) => {
onResolve = typeof onResolve === "function" ? onResolve : (data) => data
onReject = typeof onReject === "function" ? onReject : (err) => err
const newPromise = new selfPromise((resolve, reject) => {
if (this.status === RESOLVE) {
setTimeout(() => {
try {
const result = onResolve(this.result)
handlePromise(RESOLVE, result, newPromise, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
}
if (this.status === REJECT) {
setTimeout(() => {
try {
const result = onReject(this.reason)
handlePromise(REJECT, result, newPromise, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
}
if (this.status === PENDING) {
this.resolveAsyList.push(() => {
try {
const result = onResolve(this.result)
handlePromise(RESOLVE, result, newPromise, resolve, reject)
} catch (error) {
reject(error)
}
})
this.rejectAsyList.push(() => {
try {
const result = onReject(this.reason)
handlePromise(REJECT, result, newPromise, resolve, reject)
} catch (error) {
reject(error)
}
})
}
})
return newPromise
}
this.catch = (onReject) => {
return this.then(undefined, onReject)
}
}
module.exports = selfPromise
测试案例:
const myPromise = require('./myPromise_v4')
var test = new myPromise((resolve, reject) => {
setTimeout(()=>{
reject("error")
},1000)
})
test.then(res => {
console.log("res1", res)
return "then1"
}, err => {
console.log("err1",err)
return err
}).then(res => {
console.log("res2", res)
}, err => {
console.log("err2", err)
return err
}).catch(err=>{
console.log("catch",err)
})
console.log("同步代码")
至此,我们已经基本把promise对象的基本方法都实现了,除此之外,原生的promise对象还有all,race这两个方法,这个大家可以自行实现,本系列文章到此就告一段落了,如果过程中有错误的希望大家指出,感谢大家的支持,觉得本系统文章有用的老铁可以给作者点个赞,谢谢。