写在开头:如果被大佬们看到了有错误还请斧正,如果把萌新带到了沟里,你在爬出来就好了(手动滑稽)
在 myPromise 实现的过程中是没有对于异常的处理,一个成熟的类或者方法都是有对错误和异常的处理的,所以接下来处理 myPromise 中的异常情况。
1、捕获 myPromise 中的错误
1、处理回调函数执行错误的情况
let promise = new myPromise(
// 在此处就发生了错误
(resolve, reject) => {
throw new Error('出错了');
}
);
promise.then((value) => {
console.log(value);
}, (reason) => {
console.log(reason); // 这里会抛出错误
});
*
*
constructor(executor) {
try {
executor(this.resolve, this.reject);
} catch (error) {
this.reject(error);
}
}
*
*
2、处理 then 方法中回调函数发成错误的情况
let promise = new myPromise((resolve, reject) => {
resolver('成功');
}
);
promise.then((value) => {
console.log(value);
throw new Error('出错了');
}).then(() => {
// 在这里会得到上一个 then 方法抛出的错误
});
*
*
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = successCallback(this.value);
argParsing(thenPromise, x, resolve, reject);
} catch (error) {
// Q: 为啥要用 reject
// A: 链式调用 then 方法的时候,上一个发生了错误的 then 需要在下一个 then 方法中抛出
reject(error);
}
}, 0);
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = failCallback(this.reason);
argParsing(thenPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else {
this.successCallback.push(() => {
setTimeout(() => {
try {
let x = successCallback(this.value);
argParsing(thenPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.failCallback.push(() => {
setTimeout(() => {
try {
let x = failCallback(this.reason);
argParsing(thenPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
*
*
这样就捕获到了 myPromise 在运行时的异常情况
2、then 方法的参数变为可选参数
在 Promise 中 then 方法中的成功回调和失败回调是可选参数,属于可写可不写的
let promise = new Promise((resolve, reiect) => {
resolve(100);
});
promise
.then()
.then()
.then()
.then((value) => {
console.log(value); // 100
});
当在前一个 then 方法中不传递任何参数的时候,实际上等同于传递了一个返回了自己的回调函数,大概就是酱婶儿的:
所以只要判断一下这个 then 方法有没有传递参数应该就可以了,如果没有传递参数,那么就给他补一个参数
*
*
then(successCallback, failCallback) {
successCallback = successCallback ? successCallback : value => value;
failCallback = failCallback ? failCallback : reason => { throw reason };
let thenPromise = new myPromise((resolve, reject) => {
*
*
运行起来康康没啥问题
到此 Promise 的 then 方法就得到了基本的完善,目前为止代码如下:
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;
value = undefined;
reason = undefined;
successCallback = [];
failCallback = [];
resolve = (value) => {
if (this.status !== PENDING) return;
this.status = FULFILLED;
this.value = value;
while (this.successCallback.length) {
this.successCallback.shift()();
}
}
reject = (reason) => {
if (this.status !== PENDING) return;
this.status = REJECTED;
this.reason = reason;
while (this.failCallback.length) {
this.failCallback.shift()();
}
}
then(successCallback, failCallback) {
successCallback = successCallback ? successCallback : value => value;
failCallback = failCallback ? failCallback : reason => { throw reason };
let thenPromise = new myPromise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = successCallback(this.value);
argParsing(thenPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = failCallback(this.reason);
argParsing(thenPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else {
this.successCallback.push(() => {
setTimeout(() => {
try {
let x = successCallback(this.value);
argParsing(thenPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.failCallback.push(() => {
setTimeout(() => {
try {
let x = failCallback(this.reason);
argParsing(thenPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
})
return thenPromise;
}
}
function argParsing(thenPromise, x, resolve, reject) {
if (thenPromise === x) return reject(new TypeError('Promise 被循环调用了'));
if (x instanceof myPromise) {
x.then(resolve, reject);
} else {
resolve(x);
}
}
Promise 的 then 方法到此就得到的完善,然而 Promise 除了 then 方法之外还有 all,Promise.resolve,finally,catch,接下来逐一简单进行实现。