前言
📫 大家好,我是南木元元,热爱技术和分享,欢迎大家交流,一起学习进步!
🍅 个人主页:南木元元
Promise有很多静态方法,本文就来分享下如何实现这些静态方法。
目录
静态方法
实现Promise.resolve和Promise.reject
实现Promise.all
实现Promise.allSettled
实现Promise.race
实现Promise.any
实现finally实例方法
结语
静态方法
静态方法是指直接定义在类上的方法,而不是定义在类实例上的方法。它们可以通过类本身调用,而不需要创建类的实例。静态方法通常用于用于在类级别上操作数据和提供一些实用功能,而不需要实例化对象。比如,可以在 Math 类中定义一些数学计算相关的静态方法。
在上文中,我们已经实现了Promsie中最重要的resolve、reject和then方法,但上文实现的代码是不支持直接使用MyPromise.resolve和MyPromise.reject这种形式的。我们可以在Promise 类上通过static关键字直接定义静态方法,来允许对多个 Promise 对象进行操作或直接创建新的 Promise,而无需实例化一个新的 Promise 对象。
实现Promise.resolve和Promise.reject
MDN上对Promise.resolve()和Promise.reject()的定义:
1.Promise.resolve()
静态方法将给定的值转换为一个 Promise。如果该值本身就是一个 Promise,那么该 Promise 将被返回;如果该值是一个thenable对象,Promise.resolve() 将调用其then() 方法及其两个回调函数;否则,返回的 Promise 将会以该值兑现。
2.Promise.reject()
静态方法返回一个已拒绝(rejected)的Promise 对象,拒绝原因为给定的参数。
class MyPromise {
...
// resolve 静态方法,返回一个以给定值解析后的Promise对象
static resolve (param) {
// 1.传参为Promise,直接返回
if (param instanceof MyPromise) return param;
// 2.直接返回以该值为成功状态的promise对象
return new MyPromise(resolve => {
resolve(param);
});
}
// reject 静态方法,返回一个带有拒绝原因(拒绝原因为给定参数)的Promise对象
static reject (reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
}
}
测试:
MyPromise.resolve().then(() => {
console.log(0);//0
return MyPromise.resolve(4);
}).then((res) => {
console.log(res)//4
})
实现Promise.all
all方法用于将多个Promise实例包装成一个新的Promise实例,只有当所有的Promise实例都成功时,新的Promise实例才会成功。
static all(promises) {
return new Promise(function(resolve, reject) {
//传入参数为一个空的可迭代对象,直接resolve
if (promises.length === 0) {
resolve([]);
} else {
const res = [];
let count = 0;
for (let i = 0; i < promises.length; i++) {
//为什么不直接promise[i].then, 因为promise[i]可能不是一个promise, 也可能是普通值
Promise.resolve(promises[i]).then((data) => {
res[i] = data;
count++;
if (count === promises.length) {
resolve(res);//如果所有Promise都成功,则返回成功结果数组
}
}).catch((err) => {
reject(err);//如果有一个Promise失败,则返回这个失败结果
});
}
}
})
}
测试:
const promise1 = MyPromise.resolve(3);
const promise2 = 42;
const promise3 = new MyPromise((resolve, reject) => {
setTimeout(resolve, 100, "foo");
});
MyPromise.all([promise1, promise2, promise3]).then((values) => {
console.log(values); //[3, 42, "foo"]
});
实现Promise.allSettled
Promise.allSettled跟Promise.all类似, 唯一的不同在于, 其不会进行短路, 也就是说当Promise全部处理完成后我们可以拿到每个Promise的状态,而不管其是否处理成功。
当有多个彼此不依赖的异步任务成功完成时,或者您总是想知道每个Promise的结果时,通常使用它。如果任务相互依赖,或者如果你想立即拒绝其中任何任务Promise.all()方法更合适。
static allSettled(promises) {
return new Promise(function(resolve, reject) {
//传入参数为一个空的可迭代对象,直接resolve
if (promises.length === 0) {
resolve([]);
} else {
const res = [];
let count = 0;
for (let i = 0; i < promises.length; i++) {
//为什么不直接promise[i].then, 因为promise[i]可能不是一个promise, 也可能是普通值
Promise.resolve(promises[i]).then((data) => {
res[i] = {status: 'fulfilled', value: data};
count++;
if (count === promises.length) {
resolve(res);//如果所有Promise都成功,则返回成功结果数组
}
}).catch((err) => {
//失败的时候,不直接返回,而是也把当前状态保存到数组中,等执行完毕时一起返回该数组
res[i] = {status: 'rejected', value: err};
count++;
if (count === promises.length) {
resolve(res);
}
});
}
}
})
}
测试:
MyPromise.allSettled([
MyPromise.resolve(33),
new MyPromise((resolve) => setTimeout(() => resolve(66), 0)),
99,
MyPromise.reject(new Error("an error"))
]).then((values) => {
console.log(values);
});
实现Promise.race
race 的实现:只要有一个 promise 执行完,直接 resolve 并停止执行。
static race(promises) {
return new Promise(function(resolve, reject) {
//传入参数为一个空的可迭代对象,直接resolve
if (promises.length === 0) {
resolve([]);
} else {
for (let i = 0; i < promises.length; i++) {
//为什么不直接promise[i].then, 因为promise[i]可能不是一个promise, 也可能是普通值
Promise.resolve(promises[i]).then((data) => {
resolve(data); //返回最快的结果
}).catch((err) => {
reject(err); //返回最快的结果
});
}
}
})
}
测试:
const promise1 = new MyPromise((resolve, reject) => {
setTimeout(resolve, 500, 'one');
});
const promise2 = new MyPromise((resolve, reject) => {
setTimeout(resolve, 100, 'two');
});
MyPromise.race([promise1, promise2]).then((value) => {
console.log(value); //two
});
实现Promise.any
Promise.any()
静态方法会在任意一个传入的 Promise 成功时,返回该成功的结果。如果所有传入的 Promise 都被拒绝(即失败),它会以AggregateError的形式被拒绝,其中包含所有被拒绝的原因。
static any(promises) {
return new Promise(function (resolve, reject) {
//传入参数为一个空的可迭代对象,直接resolve
if (promises.length === 0) {
resolve([]);
} else {
let count = 0;
for (let i = 0; i < promises.length; i++) {
//为什么不直接promise[i].then, 因为promise[i]可能不是一个promise, 也可能是普通值
Promise.resolve(promises[i])
.then((data) => {
resolve(data); //有一个Promise成功,就返回那个结果
})
.catch((err) => {
count++;
if (count === promises.length) {
//当所有输入Promise都被拒绝时,会以一个包含拒绝原因数组的AggregateError拒绝,AggregateError对象代表了包装了多个错误对象的单个错误对象
reject(new AggregateError('All promises were rejected')); //所有Promise都失败,就报错
}
});
}
}
});
}
实现finally实例方法
无论Promise是成功还是失败,都会调用finally方法,执行 finally 中传入的函数,并且将值原封不动的往下传,以保证可以继续链式调用。
MyPromise.prototype.finally = function (callback) {
// 调用then方法,传入两个相同的处理函数,返回一个新的 Promise 对象(保证链式调用)
return this.then(
value => {
// 创建一个新的Promise实例,确保异步执行callback
return MyPromise.resolve(callback()).then(() => value);
},
reason => {
// 创建一个新的Promise实例,确保异步执行callback
return MyPromise.resolve(callback()).then(() => { throw reason; });
}
);
}
结语
🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,支持一下博主~