在上篇文章中介绍了,如何处理返回自身对象的处理,在本篇文章中将介绍如何捕获错误以及其他状态代码补充
//设置promise 状态
const PENDING = "pending"; //等待状态
const FULFILLED = 'FULFILLED'; //成功状态
const REJECTED = 'rejected'; //失败状态
class MyPromise {
constructor(executor) {
//立即调用函数
try {
executor(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
}
//初始化状态
status = PENDING
//初始化成功之后的值
success = undefined
//初始化失败之后的值
error = undefined
//用于保存成功回调,成功回调的默认值需要改成数组,因为只有数组可以存储多个回调函数
successCallback = []
//用于保存失败回调,失败回调的默认值需要改成数组,因为只有数组可以存储多个回调函数
failCallback = []
resolve = success => {
//如果状态不是等待 则阻止程序执行
if (this.status !== PENDING) return
//把promise状态改为成功
this.status = FULFILLED
//保存成功之后的值
this.success = success
//如果有这个回调,那么要执行这个回调,并且把成功的值传递进去
//this.successCallback && this.successCallback(this.success);
//现在呢数组中存储了多个回调函数,所以遍历数组的每个函数并让其执行,上面的代码已经不符合要求
//重新编写逻辑
//这里使用while语句用successCallback.length作为循环条件,如果数组中有值,拿到数组中的第一个回调函数传值并执行
while (this.successCallback.length) this.successCallback.shift()();
}
reject = error => {
//如果状态不是等待 则阻止程序执行
if (this.status !== PENDING) return
//把promise状态改为失败
this.status = REJECTED
//保存失败之后的值
this.error = error
//如果有这个回调,那么要执行这个回调,并且把失败的原因传递进去
//this.failCallback && this.failCallback(this.error);
//现在呢数组中存储了多个回调函数,所以遍历数组的每个函数并让其执行,上面的代码已经不符合要求
//重新编写逻辑
//这里使用while语句用failCallback.length作为循环条件,拿到数组中的第一个回调函数传值并执行
while (this.failCallback.length) this.failCallback.shift()();
}
then(successCallback, failCallback) {
//要实现then方法的链式调用必须创建一promise对象
//新建一个promise对象
let promise2 = new MyPromise((resolve, reject) => {
//逻辑判断如果当前状态为成功 则执行成功的回调并且把保存成功的值传递进去
if (this.status === FULFILLED) {
//此处仅仅将代码作为异步代码,延迟时间为0, 因为promise2 是在new MyPromise执行完成之后才能看到 在new MyPromise执行过程中是看不到的
//所以将代码变成异步代码
setTimeout(() => {
//捕获成功函数的错误信息
try {
//保存上一个函数的返回值
let x = successCallback(this.success)
//并且把返回值传递给下一个then方法
// resolve(x);
//判断X的值是普通值还是promise对象
//如果是普通值 直接调用resolve
//如果是promise对象 查看promise对象返回的结果
//再根据promise对象返回的结果 调用resolve还reject
//所有同步代码执行完了才能看到promise2
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
//手动调用reject方法 把错误信息传递给下一个promise函数
reject(error)
}
}, 0);
//逻辑判断如果当前状态为成功 则执行失败的回调并且把失败的原因传递进去
} else if (this.status === REJECTED) {
setTimeout(() => {
//捕获错误函数的错误信息
try {
//保存上一个函数的返回值
let x = failCallback(this.error)
//并且把返回值传递给下一个then方法
// resolve(x);
//判断X的值是普通值还是promise对象
//如果是普通值 直接调用resolve
//如果是promise对象 查看promise对象返回的结果
//再根据promise对象返回的结果 调用resolve还reject
//所有同步代码执行完了才能看到promise2
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
//手动调用reject方法 把错误信息传递给下一个promise函数
reject(error)
}
}, 0);
} else {
//当前状态为等待,也就是promise状态为pending,
//如果是等待的话那应该调用成功回调还是失败回调呢
//那当然是两个回调都无法调用,应为不知道到底是成功了还是还是失败了
//在这种情况下应该将成功回调和失败回调进行保存
//保存成功回调函数
//在这里有一个问题 this.successCallback一次只能存储一个函数这样的不符合要求
//所以在上面定义successCallback的时候将其定义为数组,这样就可以存储多个回调 ,将回调push进去
//重新编辑逻辑
this.successCallback.push(() => {
setTimeout(() => {
//捕获成功函数的错误信息
try {
//保存上一个函数的返回值
let x = successCallback(this.success)
//并且把返回值传递给下一个then方法
// resolve(x);
//判断X的值是普通值还是promise对象
//如果是普通值 直接调用resolve
//如果是promise对象 查看promise对象返回的结果
//再根据promise对象返回的结果 调用resolve还reject
//所有同步代码执行完了才能看到promise2
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
//手动调用reject方法 把错误信息传递给下一个promise函数
reject(error)
}
}, 0);
});
//重新编辑逻辑
this.failCallback.push(() => {
setTimeout(() => {
//捕获错误函数的错误信息
try {
//保存上一个函数的返回值
let x = failCallback(this.error)
//并且把返回值传递给下一个then方法
// resolve(x);
//判断X的值是普通值还是promise对象
//如果是普通值 直接调用resolve
//如果是promise对象 查看promise对象返回的结果
//再根据promise对象返回的结果 调用resolve还reject
//所有同步代码执行完了才能看到promise2
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
//手动调用reject方法 把错误信息传递给下一个promise函数
reject(error)
}
}, 0);
});
}
})
//返回promise对象
return promise2
}
}
//定义函数用于判断返回的是普通值还是promise对象
function resolvePromise(promise2, x, resolve, reject) {
//逻辑判断是返回的是当前的promise对象 如果是抛出错误并且阻止程序执行
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #' ))
}
//逻辑判断如果是promise对象
if (x instanceof MyPromise) {
//如果是成功的回调 就把值传递进去 失败的话就把失败的原因传递进去
// x.then(success => resolve(success), error => reject(error))
//下面是简写写法
x.then(resolve, reject)
} else {
//逻辑判断是普通值直接传递进去
resolve(x)
}
}
//遵循commjs规范 导出
module.exports = MyPromise;
let MyPromise = require('./手写promise-5 捕获错误及 then 链式调用其他状态代码补充');
let promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 200);
})
promise
.then(res => {
console.log(res);
return 'aaa'
}, err => {
console.log(err);
return '11111'
})
.then(res => {
console.log(res);
return 10000
}, error => {
//console.log(error)
console.log(error)
})
//打印结果
//aaa
//11111
谢谢观看,如有不足,敬请指教