最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 手写实现Promise详解

    正文概述 掘金(一依仪毅)   2020-11-29   494

    手写实现Promise详解

    中间都是实现流程想直接看源码的大佬请直接点击源码查看或从参考文档中查看

    Promise的基本语法

    const p=new Promeise((resolve,reject)=>{
    	resolve() //reject()
    })
    p.then((res)=>{},(err)=>{}).catch((err)=>{})
    

    按照基本语法实现

    一、创建一个MyPromsie类

    const p=new Promeise()
    //实现
    class MyPromsie{}
    

    二、在constructor中添加基础方法

    const p=new Promeise((resolve,reject)=>{
    	resolve() //reject()
    })
    p.then((res)=>{},(err)=>{}).catch((err)=>{})
    ///实现
    class MyPromise {
        constructor (handle) {
            // new Promeise((resolve,reject)=>{})
            try {
                //定义一个handle处理行数(resolve,reject)=>{}
                handle(this._resolve, this._reject)
            } catch (err) {
                this._reject(err)
            }
        }
        //定义函数传入的两个参数
        //成功时调用
        _resolve= val => {}
        //失败时调用
        _resolve= err> {}
        //then方法 接受两个参数 一个完成时回调函数 一个拒绝时回调函数
        then(onFulfilled, onRejected){}
    }
    

    三、完善方法先实现同步调用 异步调用在第四节

    const p=new Promeise((resolve,reject)=>{
    	resolve() //reject()
    })
    ///实现
    // 定义Promise的三种状态常量
    const PENDING = 'pending'; //等待
    const FULFILLED = 'fulfilled'; //已完成
    const REJECTED = 'rejected'; //已拒绝
    class MyPromise {
        constructor (handle) {
            // new Promeise((resolve,reject)=>{})
            try {
                //定义一个handle处理行数(resolve,reject)=>{}
                handle(this._resolve, this._reject)
            } catch (err) {
                this._reject(err)
            }
        }
        //存储完成或拒绝的值
        _value = undefined
        //存储状态 pending  fulfilled  rejected
        _status = PENDING
        //定义函数传入的两个参数
        //完成时调用
        _resolve = val => {
            //如果状态改变 就直接返回
            if (this._status !== PENDING) return;
            //状态设置为已完成
            this._status = FULFILLED
            //赋值已完成时传入的参数
            this._value = val;
        }
        //拒绝时调用
        _reject = err => {
            //如果状态改变 就直接返回
            if(this._status !== PENDING) return;
            //状态设置为拒绝
            this._status = REJECTED
            //赋值拒绝时传入的参数
        	this._value = err;
        }
        //then方法 接受两个参数 一个完成时回调函数 一个拒绝时回调函数
        then(onFulfilled, onRejected) {
            let {_status, _value} = this
            switch (_status) {
                // 当状态为pending时,将then方法回调函数加入执行队列等待执行
                case PENDING:
                    //先留到后面
                    break;
                // 当状态已经改变时,立即执行对应的回调函数
                case FULFILLED:
                    onFulfilled(_value);
                    break;
                case REJECTED:
                    onRejected(_value);
                    break;
            }
        }
    }
    module.exports = MyPromise
    
    • 代码运行结果

    手写实现Promise详解

    四、支持异步调用 在代码中添加队列

    将then传入的函数如果状态是成功直接执行,如果还在pending放入队列中,然后resole/reject函数回调后直接调用队列中的方法。(没有使用一个变量保存回调函数,而是使用队列是因为有可能出现多个p.then方法)

    手写实现Promise详解! 手写实现Promise详解 手写实现Promise详解

    • 完整代码
    const PENDING = 'pending'; //等待
    const FULFILLED = 'fulfilled'; //已完成
    const REJECTED = 'rejected'; //已拒绝
    class MyPromise {
        constructor (handle) {
            // new Promeise((resolve,reject)=>{})
            try {
                //定义一个handle处理行数(resolve,reject)=>{}
                handle(this._resolve, this._reject)
            } catch (err) {
                this._reject(err)
            }
        }
        //存储完成或拒绝的值
        _value = undefined
        //存储状态 pending  fulfilled  rejected
        _status = PENDING
        // 失败队列,在 then 时注入,resolve 时触发
        _rejectedQueues = [];
        // 成功队列,在 then 时注入,resolve 时触发
        _fulfilledQueues = [];
        //定义函数传入的两个参数
        //完成时调用
        _resolve = val => {
            //如果状态改变 就直接返回
            if (this._status !== PENDING) return;
            // 依次执行成功队列中的函数,并清空队列
            const runFulfilled = value => {
                let cb;
                while ((cb = this._fulfilledQueues.shift())) {
                    cb(value);
                }
            };
            //状态设置为已完成
            this._status = FULFILLED
            //赋值已完成时传入的参数
            this._value = val;
            runFulfilled(val)
        }
        //拒绝时调用
        _reject = err => {
            //如果状态改变 就直接返回
            if (this._status !== PENDING) return;
            //状态设置为拒绝
            this._status = REJECTED
            //赋值拒绝时传入的参数
            this._value = err;
            let cb;
            while ((cb = this._rejectedQueues.shift())) {
                cb(err);
            }
        }
        //then方法 接受两个参数 一个完成时回调函数 一个决绝时回调函数
        then(onFulfilled, onRejected) {
            let {_status, _value} = this
            switch (_status) {
                // 当状态为pending时,将then方法回调函数加入执行队列等待执行
                case PENDING:
                    this._fulfilledQueues.push(onFulfilled);
                    this._rejectedQueues.push(onRejected)
                    break;
                // 当状态已经改变时,立即执行对应的回调函数
                case FULFILLED:
                    onFulfilled(_value);
                    break;
                case REJECTED:
                    onRejected(_value);
                    break;
            }
        }
    }
    
    module.exports = MyPromise
    
    • 运行结果

    手写实现Promise详解

    五、如果promise里面返回的时另外一个Pomise对象需要等待另外一个promise返回状态后才执行当前的promise且状态取决于参数Promsie对象的状态

    列:p等待了两秒以后才返回 嘎嘎嘎 的值

    手写实现Promise详解

    • 代码片段

    手写实现Promise详解

    • 完整代码
    const PENDING = 'pending'; //等待
    const FULFILLED = 'fulfilled'; //已完成
    const REJECTED = 'rejected'; //已拒绝
    class MyPromise {
        constructor (handle) {
            // new Promeise((resolve,reject)=>{})
            try {
                //定义一个handle处理行数(resolve,reject)=>{}
                handle(this._resolve, this._reject)
            } catch (err) {
                this._reject(err)
            }
        }
        //存储完成或拒绝的值
        _value = undefined
        //存储状态 pending  fulfilled  rejected
        _status = PENDING
        // 失败队列,在 then 时注入,resolve 时触发
        _rejectedQueues = [];
        // 成功队列,在 then 时注入,resolve 时触发
        _fulfilledQueues = [];
        //定义函数传入的两个参数
        //完成时调用
        _resolve = val => {
            //如果状态改变 就直接返回
            if (this._status !== PENDING) return;
            // 依次执行成功队列中的函数,并清空队列
            const runFulfilled = value => {
                let cb;
                while ((cb = this._fulfilledQueues.shift())) {
                    cb(value);
                }
            };
             // 依次执行失败队列中的函数,并清空队列
             const runRejected = error => {
                let cb;
                while ((cb = this._rejectedQueues.shift())) {
                    cb(error);
                }
            };
            /*
               * 如果resolve的参数为Promise对象,
               * 则必须等待该Promise对象状态改变后当前Promsie的状态才会改变
               * 且状态取决于参数Promsie对象的状态
           */
            if (val instanceof MyPromise) {
                val.then(value => {
                    this._status = FULFILLED;
                    this._value = value;
                    runFulfilled(value)
                }, err => {
                    this._status = FULFILLED;
                    this._value = err;
                    runRejected(err);
                })
            } else {
                this._status = FULFILLED;
                this._value = val;
                runFulfilled(val)
            }
        }
        //拒绝时调用
        _reject = err => {
            //如果状态改变 就直接返回
            if (this._status !== PENDING) return;
            //状态设置为拒绝
            this._status = REJECTED
            //赋值拒绝时传入的参数
            this._value = err;
            let cb;
            while ((cb = this._rejectedQueues.shift())) {
                cb(err);
            }
        }
        //then方法 接受两个参数 一个完成时回调函数 一个决绝时回调函数
        then(onFulfilled, onRejected) {
            let {_status, _value} = this
            switch (_status) {
                // 当状态为pending时,将then方法回调函数加入执行队列等待执行
                case PENDING:
                    this._fulfilledQueues.push(onFulfilled);
                    this._rejectedQueues.push(onRejected)
                    break;
                // 当状态已经改变时,立即执行对应的回调函数
                case FULFILLED:
                    onFulfilled(_value);
                    break;
                case REJECTED:
                    onRejected(_value);
                    break;
            }
        }
    }
    
    module.exports = MyPromise
    
    • 运行结果 同列子

    六、then后面还是会返回一个promise可以接then

    const p=new Promeise((resolve,reject)=>{
    	resolve() //reject()
    })
    p.then((res)=>{},(err)=>{}).then((res)=>{})
    
    • 完整代码 (代码修改then部分)
    const isFunction = variable => typeof variable === 'function';
    
    const PENDING = 'pending'; //等待
    const FULFILLED = 'fulfilled'; //已完成
    const REJECTED = 'rejected'; //已拒绝
    class MyPromise {
        constructor (handle) {
            // new Promeise((resolve,reject)=>{})
            try {
                //定义一个handle处理行数(resolve,reject)=>{}
                handle(this._resolve, this._reject)
            } catch (err) {
                this._reject(err)
            }
        }
        //存储完成或拒绝的值
        _value = undefined
        //存储状态 pending  fulfilled  rejected
        _status = PENDING
        // 失败队列,在 then 时注入,resolve 时触发
        _rejectedQueues = [];
        // 成功队列,在 then 时注入,resolve 时触发
        _fulfilledQueues = [];
        //定义函数传入的两个参数
        //完成时调用
        _resolve = val => {
            //如果状态改变 就直接返回
            if (this._status !== PENDING) return;
            // 依次执行成功队列中的函数,并清空队列
            const runFulfilled = value => {
                let cb;
                while ((cb = this._fulfilledQueues.shift())) {
                    cb(value);
                }
            };
            // 依次执行失败队列中的函数,并清空队列
            const runRejected = error => {
                let cb;
                while ((cb = this._rejectedQueues.shift())) {
                    cb(error);
                }
            };
            /*
               * 如果resolve的参数为Promise对象,
               * 则必须等待该Promise对象状态改变后当前Promsie的状态才会改变
               * 且状态取决于参数Promsie对象的状态
           */
            if (val instanceof MyPromise) {
                val.then(value => {
                    this._status = FULFILLED;
                    this._value = value;
                    runFulfilled(value)
                }, err => {
                    this._status = FULFILLED;
                    this._value = err;
                    runRejected(err);
                })
            } else {
                this._status = FULFILLED;
                this._value = val;
                runFulfilled(val)
            }
        }
        //拒绝时调用
        _reject = err => {
            //如果状态改变 就直接返回
            if (this._status !== PENDING) return;
            //状态设置为拒绝
            this._status = REJECTED
            //赋值拒绝时传入的参数
            this._value = err;
            let cb;
            while ((cb = this._rejectedQueues.shift())) {
                cb(err);
            }
        }
        //then方法 接受两个参数 一个完成时回调函数 一个决绝时回调函数
        then(onFulfilled, onRejected) {
            let {_status, _value} = this
            // then返回的是一个Promise对象
            return new MyPromise((resolve, reject) => {
                // 封装一个完成时执行的函数
                const fulfilled = value => {
                    try {
                        if (!isFunction(onFulfilled)) {
                            resolve(value);
                        } else {
                            const res = onFulfilled(value);
                            if (res instanceof MyPromise) {
                                // 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
                                res.then(resolve, reject);
                            } else {
                                //否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
                                resolve(res);
                            }
                        }
                    } catch (err) {
                        // 如果函数执行出错,新的Promise对象的状态为失败
                        reject(err);
                    }
                };
                // 封装一个拒绝时执行的函数
                const rejected = err => {
                    try {
                        if (!isFunction(onRejected)) {
                            resolve(error);
                        } else {
                            const res = onRejected(err);
                            if (res instanceof MyPromise) {
                                // 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
                                res.then(resolve, reject);
                            } else {
                                //否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
                                resolve(res);
                            }
                        }
                    } catch (err) {
                        reject(err);
                    }
                }
                // console.log('_status', _status)
                switch (_status) {
                    // 当状态为pending时,将then方法回调函数加入执行队列等待执行
                    case PENDING:
                        this._fulfilledQueues.push(fulfilled);
                        this._rejectedQueues.push(rejected)
                        break;
                    // 当状态已经改变时,立即执行对应的回调函数
                    case FULFILLED:
                        fulfilled(_value);
                        break;
                    case REJECTED:
                        rejected(_value);
                        break;
                }
            })
        }
    }
    
    module.exports = MyPromise
    
    • 运行结果

    手写实现Promise详解

    以上基本是promise的主要代码下面时参考文档中的所有Promise方法的代码

    源码

    /**
     * 参考 文档  
     * https://juejin.im/post/6844903989083897870#heading-13
     * https://es6.ruanyifeng.com/#docs/promise
     *  */
    const isFunction = variable => typeof variable === 'function';
    
    const PENDING = 'pending'; //等待
    const FULFILLED = 'fulfilled'; //已完成
    const REJECTED = 'rejected'; //已拒绝
    class MyPromise {
        constructor (handle) {
            // new Promeise((resolve,reject)=>{})
            try {
                //定义一个handle处理行数(resolve,reject)=>{}
                handle(this._resolve, this._reject)
            } catch (err) {
                this._reject(err)
            }
        }
        //存储完成或拒绝的值
        _value = undefined
        //存储状态 pending  fulfilled  rejected
        _status = PENDING
        // 失败队列,在 then 时注入,resolve 时触发
        _rejectedQueues = [];
        // 成功队列,在 then 时注入,resolve 时触发
        _fulfilledQueues = [];
        //定义函数传入的两个参数
        //完成时调用
        _resolve = val => {
            //如果状态改变 就直接返回
            if (this._status !== PENDING) return;
            // 依次执行成功队列中的函数,并清空队列
            const runFulfilled = value => {
                let cb;
                while ((cb = this._fulfilledQueues.shift())) {
                    cb(value);
                }
            };
            // 依次执行失败队列中的函数,并清空队列
            const runRejected = error => {
                let cb;
                while ((cb = this._rejectedQueues.shift())) {
                    cb(error);
                }
            };
            /*
               * 如果resolve的参数为Promise对象,
               * 则必须等待该Promise对象状态改变后当前Promsie的状态才会改变
               * 且状态取决于参数Promsie对象的状态
           */
            if (val instanceof MyPromise) {
                val.then(value => {
                    this._status = FULFILLED;
                    this._value = value;
                    runFulfilled(value)
                }, err => {
                    this._status = FULFILLED;
                    this._value = err;
                    runRejected(err);
                })
            } else {
                this._status = FULFILLED;
                this._value = val;
                runFulfilled(val)
            }
        }
        //拒绝时调用
        _reject = err => {
            //如果状态改变 就直接返回
            if (this._status !== PENDING) return;
            //状态设置为拒绝
            this._status = REJECTED
            //赋值拒绝时传入的参数
            this._value = err;
            let cb;
            while ((cb = this._rejectedQueues.shift())) {
                cb(err);
            }
        }
        //then方法 接受两个参数 一个完成时回调函数 一个决绝时回调函数
        then(onFulfilled, onRejected) {
            let {_status, _value} = this
            // then返回的是一个Promise对象
            return new MyPromise((resolve, reject) => {
                // 封装一个完成时执行的函数
                const fulfilled = value => {
                    try {
                        if (!isFunction(onFulfilled)) {
                            resolve(value);
                        } else {
                            const res = onFulfilled(value);
                            if (res instanceof MyPromise) {
                                // 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
                                res.then(resolve, reject);
                            } else {
                                //否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
                                resolve(res);
                            }
                        }
                    } catch (err) {
                        // 如果函数执行出错,新的Promise对象的状态为失败
                        reject(err);
                    }
                };
                // 封装一个拒绝时执行的函数
                const rejected = err => {
                    try {
                        if (!isFunction(onRejected)) {
                            resolve(error);
                        } else {
                            const res = onRejected(err);
                            if (res instanceof MyPromise) {
                                // 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
                                res.then(resolve, reject);
                            } else {
                                //否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
                                resolve(res);
                            }
                        }
                    } catch (err) {
                        reject(err);
                    }
                }
                // console.log('_status', _status)
                switch (_status) {
                    // 当状态为pending时,将then方法回调函数加入执行队列等待执行
                    case PENDING:
                        this._fulfilledQueues.push(fulfilled);
                        this._rejectedQueues.push(rejected)
                        break;
                    // 当状态已经改变时,立即执行对应的回调函数
                    case FULFILLED:
                        fulfilled(_value);
                        break;
                    case REJECTED:
                        rejected(_value);
                        break;
                }
            })
        }
            // catch 方法
            catch(onRejected) {
                return this.then(undefined, onRejected);
            }
            // finally 方法
            finally(cb) {
                return this.then(
                    value => MyPromise.resolve(cb()).then(() => value),
                    reason =>
                        MyPromise.resolve(cb()).then(() => {
                            throw reason;
                        })
                );
            }
            // 静态 resolve 方法
            static resolve(value) {
                // 如果参数是MyPromise实例,直接返回这个实例
                if (value instanceof MyPromise) return value;
                return new MyPromise(resolve => resolve(value));
            }
            // 静态 reject 方法
            static reject(value) {
                return new MyPromise((resolve, reject) => reject(value));
            }
            // 静态 all 方法
            static all(list) {
                return new MyPromise((resolve, reject) => {
                    // 返回值的集合
                    let values = [];
                    let count = 0;
                    for (let [i, p] of list.entries()) {
                        // 数组参数如果不是MyPromise实例,先调用MyPromise.resolve
                        this.resolve(p).then(
                            res => {
                                values[i] = res;
                                count++;
                                // 所有状态都变成fulfilled时返回的MyPromise状态就变成fulfilled
                                if (count === list.length) resolve(values);
                            },
                            err => {
                                // 有一个被rejected时返回的MyPromise状态就变成rejected
                                reject(err);
                            }
                        );
                    }
                });
            }
            // 添加静态race方法
            static race(list) {
                return new MyPromise((resolve, reject) => {
                    for (let p of list) {
                        // 只要有一个实例率先改变状态,新的MyPromise的状态就跟着改变
                        this.resolve(p).then(
                            res => {
                                resolve(res);
                            },
                            err => {
                                reject(err);
                            }
                        );
                    }
                });
            }
    }
    
    module.exports = MyPromise
    

    参考文档

    • juejin.im/post/684490…
    • es6.ruanyifeng.com/#docs/promi…

    起源地下载网 » 手写实现Promise详解

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元