手写Promise

1.想要进行手写Promise,首先需要知道promise 的基本特性及用法

  1. 有一个Promise构造函数,传入resolve和reject两个参数,是两个可以执行的函数
  2. promise有三种状态:pending等待,fulfilled成功,rejected失败
  3. 状态pending 一旦转为fulfilled或者rejected,不能再更改
  4. resolve()方法为成功处理方法,将状态由pending转为fulfilled,且传入参数value
  5. reject()方法为失败处理方法,将状态由pending转为rejected,且传入参数reason
  6. then()方法接受两个参数,分别为onFulfilled和onRejected函数,当状态由pending转为fulfilled后执行onFulfilled函数,由pending转为rejected后指向onRejected函数
  7. .then()方法支持链式调用,创建Promise实例后,可以通过实例一直调用.then()方法触发
  8. 静态方法的实现:Promise.resolve(),Promise.reject(),Promise.all()

2.最终需要实现的效果:实现一个最基本的 promise案例

let p = new Promise((resolve, reject) => {
   //支持异步操作
    setTimeout(function(){
        resolve('success')
    },1000);
  //resolve('success')
  // reject('error')
})
p.then(data => {
  console.log(data)
 return data;
}).then(data=>{
    console.log(data);
})

3.实现步骤

  1. 需要创建一个Promise类,并且添加一个回调方法 callback,作为Promise 的参数
  2. callback接收resolve 和 reject 作为参数,并且resolve 和 reject为两个函数且分别接受参数value和reason
  3. 定义promise的三种状态,实现then方法:定义promise的初始状态pending(后面两个状态在执行对应函数resolve和reject后进行更改);实现then方法:传入两个函数参数(onFulfilled和onRejected)通过判断状态执行对应函数
  4. then()方法可实现异步操作(用定时器进行测试)
  5. 实现链式调用
  6. 添加静态方法

3.1需要创建一个类,并且添加一个回调方法 callback,作为Promise 的参数

        class MPromise {
            constructor(callback) {
                // 执行回调函数
                callback();
            }
        }

3.2callback接收resolve 和 reject 作为参数,并且resolve 和 reject为两个函数且分别接受参数value和reason

        class MPromise {
            constructor(callback) {
                // 定义成功返回参数。为什在构造器里面定义?
                this.value = undefined;

                // 定义失败返回参数
                this.reason = undefined;

                // 定义两个处理函数
                const resolve = (value) => {
                    this.value = value;
                    console.log(this.value);
                }

                const reject = (reason) => {
                    this.reason = reason;
                }

                // 执行回调函数
                callback(resolve,reject);
            }
        }

        // MPromise类调用
        let p = new MPromise((resolve,reject)=>{
            resolve("success");
        });

3.3定义和赋值promise的三种状态,实现then方法

定义promise的初始状态pending(后面两个状态在执行对应函数resolve和reject后进行更改)

实现then方法:传入

        class MPromise {
            constructor(callback) {
                // 定义成功返回参数。为什在构造器里面定义?
                this.value = undefined;
                // 定义失败返回参数
                this.reason = undefined;

                // 定义promise的初始状态pending(后面两个状态在执行对应函数后进行更改)
                this.state = 'pending';

                // 定义两个处理函数
                const resolve = (value) => {
                    this.value = value;
                    if(this.state === 'pending'){
                        this.state = 'fulfilled';
                    }
                }

                const reject = (reason) => {
                    this.reason = reason;
                    if(this.state === 'pending'){
                        this.state = 'rejected';
                    }
                }

                // 执行回调函数
                callback(resolve,reject);
            }
            // then方法时MPromise创建的实例调用的所以在constructor外
            // then()方法会接受两个函数参数(onFulfilled和onRejected)
            then(onFulfilled,onRejected){
                // 容错:onFulfilled,onRejected存在且为function时才能进行调用
                let onFulfilledState = onFulfilled ? typeof onFulfilled === 'function' : true; //判断如果onFulfilled传入了则继续判断是否为function函数,否则直接返回true传入什么返回什么
                let onRejectedState = onRejected ? typeof onRejected === 'function' : true;
                if(onFulfilledState && onRejectedState){
                    // 根据对应状态调用不同的处理函数
                    if(this.state === 'fulfilled'){
                        onFulfilled(this.value);
                    }
                    
                    if(this.state === 'rejected'){
                        onRejected(this.value);
                    }
                }
            }
        }

        // MPromise类调用
        let p = new MPromise((resolve,reject)=>{
            resolve("success");
        });
        p.then((data)=>{
            console.log(data);
        });

3.4 then()方法可实现异步操作

以上代码,如果加入定时器实现异步就会发现打印不了

        // MPromise类调用
        let p = new MPromise((resolve,reject)=>{
            setTimeout(function (){
            resolve("success");
           },1000)
        });
        p.then((data)=>{
            console.log(data);
        });

给then方法加入返回值 new MPromise发现还是没有返回

            then(onFulfilled, onRejected) {
                return new MPromise((resolve, reject) => {
                    // 容错:onFulfilled,onRejected存在且为function时才能进行调用
                    let onFulfilledState = onFulfilled ? typeof onFulfilled === 'function' : true; //判断如果onFulfilled传入了则继续判断是否为function函数,否则直接返回true传入什么返回什么
                    let onRejectedState = onRejected ? typeof onRejected === 'function' : true;
                    if (onFulfilledState && onRejectedState) {
                        
                        // 根据对应状态调用不同的处理函数
                        if (this.state === 'fulfilled') {
                            resolve(onFulfilled(this.value));
                        }

                        if (this.state === 'rejected') {
                            reject(onRejected(this.value));
                        }
                    }
                });
            }

 为什么加入了new MPromise()后还是没有返回?因为这里是通过setTimeout()进行异步操作,当执行then方法时,回调函数中的resolve()并未执行完成,就会导致状态一直是pending

分析:发现p.then方法里面的函数不会触发,setTimeout()里面的resolve也没有执行

为什么加入了new MPromise()后还是没有返回?因为new MPromise()时,发现setTimeout()定时任务就会将其放到异步队列里面,而通过p.then()调用方法时,回调函数中的resolve()并未执行完成,this.state状态一直处于pending状态,自然也就没有调用resolve(onFulfilled())方法

解决思路:(观察者模式)

既然 then 自己无法知道 resolve 什么时候执行,是否执行了,那resolve执行完后就需要有个东西告诉then,执行完了。

即在then里面判断为pending状态时,将成功和失败的方法分别记录到一个数组里面,然后再分别再resolve()和reject()触发时,再去遍历执行数组存进去的函数

关键代码:

                // 设置数组用于存放异步队列中所有的resolve和reject函数
                this.onResolveCallback = [];
                this.onRejectCallback = [];

                // 定义两个处理函数
                const resolve = (value) => {
                    this.value = value;
                    if (this.state === 'pending') {
                        this.state = 'fulfilled';
                    }
                    if (this.state === 'fulfilled') {
                        this.onResolveCallback.forEach(resolveCb => resolveCb(this.value));
                    }
                }

                const reject = (reason) => {
                    this.reason = reason;
                    if (this.state === 'pending') {
                        this.state = 'rejected';
                    }
                    if (this.state === 'rejected') {
                        this.onRejectCallback.forEach(rejectCb => rejectCb(this.reason));
                    }
                }
.......
// 当异步执行时,状态会一直为pending
    if(this.state === 'pending') {

      this.onResolveCallback.push(() => {
        onFulfilled(this.value)
      })
      this.onRejectCallback.push(() => {
        onRejected(this.reason)
      })
    }

完整代码:

       class MPromise {
            constructor(callback) {
                // 定义成功返回参数。为什在构造器里面定义?
                this.value = undefined;
                // 定义失败返回参数
                this.reason = undefined;

                // 定义promise的初始状态pending(后面两个状态在执行对应函数后进行更改)
                this.state = 'pending';

                // 设置数组用于存放异步队列中所有的resolve和reject函数
                this.onResolveCallback = [];
                this.onRejectCallback = [];

                // 定义两个处理函数
                const resolve = (value) => {
                    this.value = value;
                    if (this.state === 'pending') {
                        this.state = 'fulfilled';
                    }
                    if (this.state === 'fulfilled') {
                        this.onResolveCallback.forEach(resolveCb => resolveCb(this.value));
                    }
                }

                const reject = (reason) => {
                    this.reason = reason;
                    if (this.state === 'pending') {
                        this.state = 'rejected';
                    }
                    if (this.state === 'rejected') {
                        this.onRejectCallback.forEach(rejectCb => rejectCb(this.reason));
                    }
                }

                // 执行回调函数
                callback(resolve, reject);
            }
            // then方法时MPromise创建的实例调用的所以在constructor外
            // then()方法会接受两个函数参数(onFulfilled和onRejected)
            then(onFulfilled, onRejected) {
                return new MPromise((resolve, reject) => {
                    // 容错:onFulfilled,onRejected存在且为function时才能进行调用
                    let onFulfilledState = onFulfilled ? typeof onFulfilled === 'function' : true; //判断如果onFulfilled传入了则继续判断是否为function函数,否则直接返回true传入什么返回什么
                    let onRejectedState = onRejected ? typeof onRejected === 'function' : true;
                    if (onFulfilledState && onRejectedState) {

                        // 根据对应状态调用不同的处理函数
                        if (this.state === 'fulfilled') {
                            resolve(onFulfilled(this.value));
                        }

                        if (this.state === 'rejected') {
                            reject(onRejected(this.value));
                        }
                        // 当异步执行时,状态会一直为pending
                        if (this.state === 'pending') {
                                // push进去的是下一次resolve函数
                                            
                       this.onResolveCallback.push(()=>onFulfilled(this.value));                               
                        this.onRejectCallback.push(()=>onRejected(this.reason));
                        }
                    }
                });
            }
        }

        // MPromise类调用
        let p = new MPromise((resolve, reject) => {
            setTimeout(function () {
                resolve("success");
                // reject("error");
            }, 1000)
        });
        p.then((data) => {
            console.log(data);
            return data
        },err=>{
            console.log(err);
        }).then((data)=>{
            console.log("第二次调用then",data);
            
        })

3.5实现链式调用

链式调用的本质是需要调用then方法后返回一个promise对象,且内部仍然会执行resolve和reject函数

特点:后面每个.then()方法中能获得上一个.then()返回的参数

解决:push进数组时再通过resolve方法执行就能重新通过then进行调用

                        // 当异步执行时,状态会一直为pending
                        if (this.state === 'pending') {
                                this.onResolveCallback.push(()=>resolve(onFulfilled(this.value)));
                                this.onRejectCallback.push(()=>resolve(onRejected(this.reason)));
                        }

3.6添加静态方法(Promise.resolve,Promise.reject,Promise.all)

其实就是单独调用new MPromise里面的resolve方法

            // 其实就是单独调用new MPromise里面的resolve方法
            static resolve = (value) => new MPromise((resolve,reject)=>resolve(value));
            static reject = (reason) => new MPromise((resolve,reject)=>resolve(reason));

        MPromise.resolve("这是静态方法MPromise.resolve调用").then((data)=>{
            console.log(data);
            return data;
        }).then(data=>{
            console.log("第二次调用静态方法MPromise.resolve调用",data);

        })
        MPromise.reject("这是静态方法MPromise.reject调用").then((error)=>{
            console.log(error);
        })

MPromise.all() 关键是需要在循环中调用promise.then()方法向下执行,最后判断数组中所有promise执行完后,通过resolve返回结果

            static all = (promiseArr) => new MPromise((resolve, reject)=>{
                // 使用数组存放所有MPromise传入的参数数据
                let results = [];
                // 使用count记录处理的MPromise,每处理一个+1,直到最后一个处理完就返回参数数组
                let count = 0;
                promiseArr.forEach((promise,index)=>{
                    promise.then(item=>{
                        results[index] = item;
                        count++;
                        console.log(promise.value);
                        // 注意此处用数组下标判断会出现问题:setTimeout()异步的会等results其他输出后第二次输出
                        if(count === promiseArr.length){
                            resolve(results);
                        }
                    });
                    
                });
            })

        let p1 = new MPromise(1);
        let p2 = new MPromise((resolve, reject) => {
            setTimeout(function(){
                resolve("p2");
            }, 2000);
        })
        let p3 = new MPromise((resolve, reject) => {
            resolve("p3");
        })
        let p4 = new MPromise((resolve, reject) => {
            resolve("p4");
        })

        MPromise.all([p1, p2, p3, p4]).then(result => {
            console.log(result);
        });

4.问题(实现Promise.all()时为什么不能通过数组循环的index判断if( index+1 === promiseArr.length )所有的promise已执行完成可以返回结果了)

手写promise中,Promise.all方法实现时,为什么不能使用index进行判断(异步时不会同时打印,等其他打印完再打印异步的)

使用index判断打印的结果为:p1,p3,p4。p2过一秒后才打印

            static all = (promiseArr) => new MPromise((resolve, reject)=>{
                // 使用数组存放所有MPromise传入的参数数据
                let results = [];
                // 使用count记录处理的MPromise,每处理一个+1,直到最后一个处理完就返回参数数组
                let count = 0;
                promiseArr.forEach((promise,index)=>{
                    promise.then(item=>{
                        results[index] = item;
                        count++;
                        console.log(promise.value);
                        // 注意此处用数组下标判断会出现问题:setTimeout()异步的会等results其他输出后第二次输出
                        if(count === promiseArr.length){
                            resolve(results);
                        }
                    });
                    
                });
            })

问题分析:

promise.then()被调用才能表示当前promise执行完,而index是在外层的,所以用index判断会输出有问题 

5.完整代码

 /*
        实现功能:
            有一个Promise构造函数,传入resolve和reject两个参数,是两个可以执行的函数
            promise有三种状态:pending等待,fulfilled成功,rejected失败
            状态pending 一旦转为fulfilled或者rejected,不能再更改
            resolve()方法为成功处理方法,将状态由pending转为fulfilled,且传入参数value
            reject()方法为失败处理方法,将状态由pending转为rejected,且传入参数reason
            then()方法接受两个参数,分别为onFulfilled和onRejected函数,当状态由pending转为fulfilled后执行onFulfilled函数,由pending转为rejected后指向onRejected函数
            .then()方法支持链式调用,创建Promise实例后,可以通过实例一直调用.then()方法触发
            静态方法的实现:Promise.resolve(),Promise.reject(),Promise.all()
        基本步骤:
            需要创建一个Promise类,并且添加一个回调方法 callback,作为Promise 的参数
            callback接收resolve 和 reject 作为参数
            定义promise的三种状态,实现then方法
            then()方法可实现异步操作(用定时器进行测试)
            实现链式调用
            添加静态方法
        */
        // 问题:写在constructor里面的函数和写在constructor外的函数区别
        // constructor里面的函数,通过构造方法创建时就必须传入回调函数
        class MPromise {
            constructor(callback) {
                // 定义成功返回参数。为什在构造器里面定义?
                this.value = undefined;
                // 定义失败返回参数
                this.reason = undefined;

                // 定义promise的初始状态pending(后面两个状态在执行对应函数后进行更改)
                this.state = 'pending';

                // 设置数组用于存放异步队列中所有的resolve和reject函数
                this.onResolveCallback = [];
                this.onRejectCallback = [];

                // 定义两个处理函数
                const resolve = (value) => {
                    this.value = value;
                    if (this.state === 'pending') {
                        this.state = 'fulfilled';
                    }
                    if (this.state === 'fulfilled') {
                        this.onResolveCallback.forEach(resolveCb => resolveCb(this.value));
                    }
                }

                const reject = (reason) => {
                    this.reason = reason;
                    if (this.state === 'pending') {
                        this.state = 'rejected';
                    }
                    if (this.state === 'rejected') {
                        this.onRejectCallback.forEach(rejectCb => rejectCb(this.reason));
                    }
                }

                // 执行回调函数(对传入非function的进行处理)
                typeof callback === 'function'? callback(resolve, reject): resolve(callback);
            }
            // then方法时MPromise创建的实例调用的所以在constructor外
            // then()方法会接受两个函数参数(onFulfilled和onRejected)
            then(onFulfilled, onRejected) {
                return new MPromise((resolve, reject) => {
                    // 容错:onFulfilled,onRejected存在且为function时才能进行调用
                    let onFulfilledState = onFulfilled ? typeof onFulfilled === 'function' : true; //判断如果onFulfilled传入了则继续判断是否为function函数,否则直接返回true传入什么返回什么
                    let onRejectedState = onRejected ? typeof onRejected === 'function' : true;
                    if (onFulfilledState && onRejectedState) {

                        // 根据对应状态调用不同的处理函数
                        if (this.state === 'fulfilled') {
                            resolve(onFulfilled(this.value));
                        }

                        if (this.state === 'rejected') {
                            reject(onRejected(this.value));
                        }
                        // 当异步执行时,状态会一直为pending
                        if (this.state === 'pending') {
                            // push进去的是下一次resolve函数
                            this.onResolveCallback.push(() => resolve(onFulfilled(this.value)));
                            this.onRejectCallback.push(() => resolve(onRejected(this.reason)));
                        }
                    }
                });
            }

            // 其实就是单独调用new MPromise里面的resolve方法
            static resolve = (value) => new MPromise((resolve, reject) => resolve(value));
            static reject = (reason) => new MPromise((resolve, reject) => resolve(reason));

            // 关键是需要在循环中调用promise.then()方法向下执行,最后判断数组中所有promise执行完后,通过resolve返回结果
            static all = (promiseArr) => new MPromise((resolve, reject)=>{
                // 使用数组存放所有MPromise传入的参数数据
                let results = [];
                // 使用count记录处理的MPromise,每处理一个+1,直到最后一个处理完就返回参数数组
                let count = 0;
                promiseArr.forEach((promise,index)=>{
                    promise.then(item=>{
                        results[index] = item;
                        count++;
                        console.log(promise.value);
                        // 注意此处用数组下标判断会出现问题:setTimeout()异步的会等results其他输出后第二次输出
                        if(count === promiseArr.length){
                            resolve(results);
                        }
                    });
                    
                });
            })
        }

        // // MPromise类调用
        // let p = new MPromise((resolve, reject) => {
        //     setTimeout(function () {
        //         resolve("success");
        //         // reject("error");
        //     }, 1000)
        // });
        // p.then((data) => {
        //     console.log(data);
        //     return data
        // },err=>{
        //     console.log(err);
        // }).then((data)=>{
        //     console.log("第二次调用then",data);

        // })

        // MPromise.resolve("这是静态方法MPromise.resolve调用").then((data)=>{
        //     console.log(data);
        //     return data;
        // }).then(data=>{
        //     console.log("第二次调用静态方法MPromise.resolve调用",data);

        // })
        // MPromise.reject("这是静态方法MPromise.reject调用").then((error)=>{
        //     console.log(error);
        // })

        let p1 = new MPromise(1);
        let p2 = new MPromise((resolve, reject) => {
            setTimeout(function(){
                resolve("p2");
            }, 2000);
        })
        let p3 = new MPromise((resolve, reject) => {
            resolve("p3");
        })
        let p4 = new MPromise((resolve, reject) => {
            resolve("p4");
        })

        MPromise.all([p1, p2, p3, p4]).then(result => {
            console.log(result);
        });


        // // Promise类调用
        // let p = new Promise((resolve, reject) => {
        //     // 执行resolve或者reject函数,并传入参数
        //    setTimeout(function (){
        //         resolve("success");
        //    },1000)
        // });
        // p.then((data) => {
        //     console.log(data);
        // })

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值