手撕Promise,实现then|catch|finally|all|allSettled|race|any|try|resolve|reject等方法

myPromise.js

模拟实现方法

  1. then方法: 用于注册成功和失败的回调函数

  2. catch方法: 用于注册失败的回调函数

  3. finally方法: 无论promise状态如何,都会执行的回调函数

  4. all方法: 多个异步操作并行执行,等待所有操作完成后返回结果

  5. allSettled方法: 多个异步操作并行执行,等待所有操作完成后返回结果,无论操作成功还是失败

  6. race方法: 多个异步操作并行执行,返回第一个完成(成功或失败)的操作结果

  7. any方法: 多个异步操作并行执行,返回第一个成功(只看成功)的操作结果

  8. try方法: 用于处理同步或异步操作,返回promise对象

  9. resolve方法: 用于返回成功的promise对象

  10. reject方法: 用于返回失败的promise对象

    // 处理循环任务
    const resolvePromise = (p, resolve, reject,promiseNext) => {
    // 处理循环任务
    if (p === promiseNext) {
    return reject(new TypeError('Uncaught (in promsie) TypeError:detected for promise #<Promsie>'));
    }

    复制代码
    // 判断x是否是myPromise实例对象

    if (p instanceof MyPromise) {
    p.then(resolve, reject);
    } else {
    resolve(p);
    }
    }

    // 手写一个promise
    class MyPromise {
    constructor(executor) {
    // promise状态
    this.status = 'pending';
    // 成功的值
    this.success = null;
    // 失败的值
    this.fail = null;
    // 成功回调函数
    this.successCallbacks = [];
    // 失败回调函数
    this.failCallbacks = [];

    复制代码
       // resolve函数
       const resolve = (success) => {
           // 判断状态
           if (this.status === 'pending') {
               this.status = 'fulfilled';
               this.success = success;
               // 执行成功回调函数
               if (this.successCallbacks.length) {
                    this.successCallbacks.forEach(callback => callback(success));
               }
           }
       }
    
       // reject函数
       const reject = (fail) => {
           // 判断状态
           if (this.status === 'pending') {
               this.status = 'rejected';
               this.fail = fail;
               // 执行失败回调函数
               if (this.failCallbacks.length) {
                    this.failCallbacks.forEach(callback => callback(fail));
               }
           }
       }
    
       try {
        // 执行executor函数
            executor(resolve, reject);
       } catch (err) {
            reject(err)
       }
    }
    
    // then方法
    then(onFulfilled, onRejected) {
       // 判断函数是否为空
       onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : success => success;
       onRejected = typeof onRejected === 'function' ? onRejected : fail => { throw fail };
    
       const primiseNext = new MyPromise((resolve,reject) => {
                // 判断成功状态
                if (Object.is(this.status, 'fulfilled')) {
                    // 使用微任务
                    queueMicrotask(() => {
                            try {
                                const result = onFulfilled(this.success);
                                resolvePromise(result, resolve, reject,primiseNext);
                            } catch (error) {
                                reject(error);
                            }
                    })
                }
    
               // 判断失败状态
               if (Object.is(this.status, 'rejected')) {
                    queueMicrotask(() => {
                        try {
                            const result = onRejected(this.fail);
                            resolvePromise(result, resolve, reject,primiseNext);
                        } catch (error) {
                            reject(error);
                        }
                    })
               }
    
               // 初始的状态
               if (Object.is(this.status, 'pending')) {
                    // 收集成功回调
                    this.successCallbacks.push(() => {
                        queueMicrotask(() => {
                            try {
                                const result = onFulfilled(this.success);
                                resolvePromise(result, resolve, reject,primiseNext);
                            } catch (error) {
                                reject(error);
                            }
                        })
                    })
    
                    // 收集失败回调
                    this.failCallbacks.push(( () => {
                        queueMicrotask(() => {
                            try {
                                const result = onRejected(this.fail);
                                resolvePromise(result, resolve, reject,primiseNext);
                            } catch (error) {
                                reject(error);
                            }
                        })
                    }))
               }
            }
       );
    
       // 返回新的promise实例对象
       return primiseNext;
    }
    
     // catch方法
     catch(onRejected) {
        return this.then(undefined, onRejected);
    }
    
       // 静态方法
    finally(fn) {
        return this.then(success => {
            fn();
            return success;
        }, fail => {
            fn();
            throw fail
        });
    }
    
    // resolve 静态方法
    static resolve(value) {
        // 是否是myPromise实例对象
        if (value instanceof MyPromise) {
            return value;
        }
        // 不是的话需要包装成myPromise实例对象
        return new MyPromise(resolve => resolve(value));
    }
    
    // reject静态方法
    static reject(fail) {
        // 是否是myPromise实例对象
        if (fail instanceof MyPromise) {
            return fail;
        }
        // 包装成myPromise实例对象
        return new MyPromise((resolve, reject) => reject(fail));
    }
    
    
    // 实现一个all静态方法, 要不全部执行成功,要不失败退出循环
    static all(promiseArr) {
        // 返回一个promise结果
        return new MyPromise((resolve, reject) => {
            const len = promiseArr.length;
           // 判断参数长度是否为空
            if (Object.is(len, 0)) {
                resolve([]);
            } else {
                // 要不全部执行成功,要不失败退出循环
                const res = [];
                let successCount = 0;
                for (let i = 0; i < len; i++) {
                  promiseArr[i]?.then(data => {
                    res[i] = data;
                    // 判断是否完成全部,全部执行成功之间触发resolve返回结果
                    if (Object.is(++successCount, len)) {
                        resolve(res);
                    }
                  }, err => {
                    reject(err);
                    return; // 结果循环
                  })
                }
            }
        })
    }
    
    // allSettled静态方法 将所有成功或者失败都返回结果
    static allSettled(promiseArr) {
        return new MyPromise((resolve, reject) => {
                if (Object.is(promiseArr.length, 0)) {
                     resolve([]);
                } else {
                    const res = [];
                    promiseArr.forEach((promise,index) => {
                        promise.then(sucess => {
                            res[index] = ({status: 'fulfilled', value: sucess});
                        },fail => {
                            res[index] = ({status: 'rejected', reason: fail});
                        })
                    });
                    resolve(res);
                }
        })
    }
    
    // race静态方法, 有一个执行成功或失败,就返回结果
    static race(promiseArr) {
        // 返回一个promise结果
        return new MyPromise((resolve, reject) => {
            const len = promiseArr.length;
           // 判断参数长度是否为空
            if (Object.is(len, 0)) {
                resolve([]);
            } else {
                // 有一个执行成功或失败,就返回结果
                for (const promise of promiseArr) {
                    promise.then(resolve, reject);
                }
            }
        })
    }
    
    // any静态方法, 有一个执行成功,就返回结果
    static any(promiseArr) {
        // 返回一个promise结果
        return new MyPromise((resolve, reject) => {
            const len = promiseArr.length;
           // 判断参数长度是否为空
            if (Object.is(len, 0)) {
                reject(new AggregateError('All promises were rejected'));
            } else {
                // 有一个执行成功,就返回结果
                let failCount = 0;
                for (let i = 0; i < len; i++) {
                  promiseArr[i]?.then(sucess => {
                    resolve(sucess);
                    return; // 结束循环
                  }, fail => {
                    // 判断是否完成全部,全部执行失败之间触发reject返回结果
                    if (Object.is(++failCount, len)) {
                        reject(fail);
                    }
                  });
                }
            }
        })
    }
    
    // try静态方法
    static try (fn) {
        return new MyPromise((resolve, reject) => {
            try {
                resolve(fn());
            } catch (error) {
                reject(error);
            }
        })
    }

    }

以下做一些简答测试

测试MyPromise

复制代码
const pro = new MyPromise((resolve, reject) => {
    resolve('success');
}).then(res => {
    console.log('then1', res); // then1 success
    x
}).then(res => {
    console.log('then2', res); // then2 undefined
}).catch(err => {
    console.log('catch1', err);  // 多个catch只执行一个
}).catch(err => {
    console.log('catch2', err);  
}).finally(() => {
    console.log('finally1');
}).finally(() => {
    console.log('finally2');
})

测试MyPromise.all方法

复制代码
MyPromise.all([
    new MyPromise((resolve, reject) => {
        setTimeout(() => {
            resolve(100);
        }, 1000);
    }),
    new MyPromise((resolve, reject) => {
        setTimeout(() => {
            resolve(200);
        }, 2000);
    }),
    new MyPromise((resolve, reject) => {
        setTimeout(() => {
            resolve(300);
        }, 3000);
    })
]).then(res => {
    console.log(res); // [ 100, 200, 300 ]
})

测试allSettled方法,将成功和失败都返回

复制代码
MyPromise.allSettled([
    new MyPromise((resolve, reject) => {
        resolve(100);
    }),
    new MyPromise((resolve, reject) => {
       reject(200);
    }),
    new MyPromise((resolve, reject) => {
        resolve(300);
    })
]).then(res => {
    console.log(res); // [ { status: 'fulfilled', value: 100 }, { status: 'rejected', reason: 200 }, { status: 'fulfilled', value: 300 } ]
})

测试MyPromise.any方法 有一个成功就可以成功结果

复制代码
MyPromise.any([
    new MyPromise((resolve, reject) => {
        setTimeout(() => {
            reject(100);
        }, 10);
    }),
    new MyPromise((resolve, reject) => {
        setTimeout(() => {
            reject(200);
        }, 20);
    }),
    new MyPromise((resolve, reject) => {
        setTimeout(() => {
            resolve(300);
        }, 30);
    })
]).then(res => {
    console.log(res); // 300
})

测试MyPromise.race方法,有一个成功或者失败就可以返回结果

复制代码
MyPromise.race([
    MyPromise.resolve(1),
    MyPromise.reject(2),
    MyPromise.resolve(3)
]).then(res => {
    console.log('promise resolve', res); // 1
}).catch(err => {
    console.log('promise reject', err); // 1
})

测试MyPromise.try方法, 可以捕获同步代码异常

复制代码
MyPromise.try(() => {
    // 在这里面其实就是加了try catch这样功能,并优雅返回promise
    console.log('try success');
}).then(res => {
    console.log(res); // try success
}).catch(err => {
    console.log(err);
})
相关推荐
崔庆才丨静觅16 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606117 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了17 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅17 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅18 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅18 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment18 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅18 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊18 小时前
jwt介绍
前端
爱敲代码的小鱼19 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax