手撕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);
})
相关推荐
张较瘦_2 小时前
前端 | 吃透CSS视觉特效:圆角、渐变、动画与变换核心解析
前端·css
Tzarevich2 小时前
Tailwind CSS:原子化 CSS 的现代开发实践
前端·javascript·css
借个火er2 小时前
React 19 源码揭秘(二):useState 的实现原理
前端
微爱帮监所写信寄信2 小时前
微爱帮监狱寄信写信小程序:深入理解JavaScript中的Symbol特性
开发语言·javascript·网络协议·小程序·监狱寄信·微爱帮
前端小臻2 小时前
RustFs 前端开发
javascript·vue.js·rustfs
syt_10132 小时前
js基础之-如何理解js中一切皆对象的说法
开发语言·javascript·原型模式
十五0012 小时前
若依集成微软单点登录(SSO)
javascript·microsoft
YaeZed2 小时前
Vue3-插槽slot
前端·vue.js
Irene19912 小时前
JavaScript 三种类型检测方法对比(instanceof、typeoff、Object.prototype.toString.call())
javascript·类型检测