ES6之手写Promise后续
/**
*
* @param {Function} onRejected 失败的回调函数
* @returns
*/
catch(onRejected) {
return this.then(null, onRejected);
}
/**
* 不论传什么函数,都会成功
* @param {Function} onSettled
*/
finally(onSettled) {
return this.then((data)=>{
onSettled();
return data;
}, (reason)=>{
onSettled();
throw reason;
})
}
我们想要实现 catch ,可以直接套用 then 方法,只需要将第一个参数设为 null ,finally 方法是不论传递的函数是什么都会返回之前的结果,并且成功执行。除了在函数中出现报错,会把错误的结果返回。所以可以直接返回一个 Promise ,返回相关的数据。所以可以在返回的 then 里面套两个函数,都调用函数,然后将上一个结果和错误返回,不返回 finally 的数据。
/**
* 返回一个Promise对象
* 如果是原来的Promise对象,直接返回
* 如果是PromiseLike,手动处理,返回和前面一样的状态
* 否则返回成功结果
* @param {any} data
*/
static resolve(data) {
if(data instanceof MyPromise){
return data;
}
return new MyPromise((resolve, reject) => {
if(isPromise(data)){
data.then(resolve, reject);
}else{
resolve(data);
}
});
}
/**
* 直接返回失败的Promise
* @param {any} reason
* @returns
*/
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
}
官方对 resolve 是这么规定的。如果是传递一个 Promise ,则直接返回,如果传递一个类似于 Promise 的函数,先判断它是否满足 A+ 规范,如果满足则返回 then 的结果。否则返回一个成功的结果。对于 reject ,直接返回一个失败的结果。
/**
* 静态方法,只有全部成功才成功,返回有顺序的结果
* 如果失败,返回失败的第一个原因
* @param {iterator} proms
* @returns
*/
static all(proms) {
return new MyPromise((resolve, reject) => {
try {
let count = 0;//总个数
let fulfilledCount = 0 //成功个数
const results = [];//最后结果
for (const p of proms) {
let i = count;
// console.log(i);
count++;
MyPromise.resolve(p).then(data => {
fulfilledCount++;
results[i] = data;
if (fulfilledCount === count) {
resolve(results);
console.log(results, 'results')
}
}, reject);
}
if(count === 0){
resolve(results);
}
} catch (error) {
reject(error);
console.error(error);
}
});
}
all 方法只要有一个失败则都会失败,我们可以定义一个总个数和成功个数,如果相等就表示成功返回结果,如果失败就返回失败的原因。因为参入的是迭代器,不一定支持索引能使用for循环,所以使用forof循环。同时为了保持数组内原始的顺序,需要将索引对应的结果提前保存。如果传入的是一个空数组,则直接返回空数组。
/**
* 不管成功还是失败都会返回所有的结果
* @param {iterator} proms
*/
static allSettled(proms) {
const ps = [];//存放所有的promise
for (const p of proms) {
ps.push(MyPromise.resolve(p).then((value) => ({
status: FULFILLED,
value,
}), (reason) => ({
status: REJECTED,
reason,
})))
}
return MyPromise.all(ps);
}
我们可以利用 all 方法,只需要一个完全成功的数组。如果数组的每一项成功和失败我们都去输出结果,每一项都是成功的,这时将结果传给 all 方法,就可以返回所有的有顺序的结果。
/**
* 只要有一个先有结果,就返回这个结果
* @param {iterator} proms
*/
static race(proms) {
return new MyPromise((resolve, reject) => {
for (const p of proms) {
MyPromise.resolve(p).then(resolve, reject);
}
});
}
可以直接调用 then 方法,看是否成功还是失败。这个过程只会执行一次,后续不会再继续进行。