目录
前言
最近练习了一下 promise 的基本使用,同时也尝试着简单手写一下 promise 的静态方法,这里将它们记录下来,方便日后温习。在下面手写实现的方法中多用到了闭包,如有不了解可以先了解了再来看这篇文章,便于理解。想了解 Promise 相关基础知识请移步 MDN-Promise。
手写代码
all
Promise.myAll = function (promises) {
if(!Array.isArray(promises)) { //判断一下传入的参数是否为数组
return Promise.reject(new Error('传入的参数不是数组!'))
};
if(!promises.length){
return Promise.resolve([]);
}
let arr = [];
let num = 0;
return new Promise((resolve, reject) => {
promises.forEach((item, index) => {
Promise.resolve(item).then((value) => { // Promise.resolve(item) 将非 Promise 包装成 Promise
num ++;
arr[index] = value;
if(num === promises.length){
resolve(arr);
}
}).catch(reject) // then 后面第二个参数也可放 reject 或者放 (value) => {reject(value);}
}
)
})
}
allSettled
Promise.myAllSettled = function(promises){
if(!Array.isArray(promises)) { //判断一下传入的参数是否为数组
return Promise.reject(new Error('传入的参数不是数组!'))
};
if(!promises.length){
return Promise.resolve([]);
}
let arr = [];
let num = 0;
return new Promise((resolve) => {
let processing = function(res, index, status, valueOrReason){
num++;
let obj = {
status:status,
}
obj[valueOrReason] = res;
arr[index] = obj;
if(num === promises.length){
resolve(arr);
}
};
promises.forEach((item, index) => {
Promise.resolve(item).then((res) => {
processing(res, index, 'fulfilled', 'value');
}, (res) => {
processing(res, index, 'rejected', 'reason');
})
})
})
}
race
Promise.myRace = function(promises){
if(!Array.isArray(promises)) { //判断一下传入的参数是否为数组
return Promise.reject(new Error('传入的参数不是数组!'));
};
if(!promises.length){
return Promise.reject(new Error('All promises were rejected'));
}
return new Promise((resolve, reject) => {
promises.forEach((item) => {
Promise.resolve(item).then(resolve, reject);
})
})
}
any
Promise.myAny = function(promises){
if(!Array.isArray(promises)) { //判断一下传入的参数是否为数组
return Promise.reject(new Error('传入的参数不是数组!'))
};
if(!promises.length){
return Promise.reject(new Error('All promises were rejected'));
}
let num = 0;
return new Promise((resolve, reject) => {
promises.forEach((item) => {
Promise.resolve(item).then(resolve, () => {
num ++;
if(num === promises.length){
reject(new Error('没有Promise完成'));
}
})
})
})
}
测试及对比
// Promise 测试数据
let p1 = function(){
return Promise.reject(1);
}
let p2 = function(){
return Promise.reject(2);
}
let p3 = function(){
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(3);
}, 2001)
});
}
let p4 = function () {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(4);
}, 2002);
});
}
// myAllSettled 测试输出和原方法简单对比,其他几个方法也可进行类似测试
console.log(Promise.allSettled([p1(), p2(), p3(), p4()]))
console.log(Promise.myAllSettled([p1(), p2(), p3(), p4()]))
console.log(Promise.allSettled([]))
console.log(Promise.myAllSettled([]))