手写Promise

前言

promise的实现主要有三步:

    一.实现原型调用

    二.解决异步调用

    三.解决链式调用

实现原型调用

       首先明确我们的需求:promise的基本使用为:

       let p2 = new Promise((res, rej) => {            res()        })        p2.then(() => {            console.log('resolve then');        })
复制代码

根据以上基本用法,我们知道我们需要实现的类具有具有以下特点:

  •      具有绑定在原型链上的then函数
  •     声明参数为一个具有resolve跟reject函数的立即执行函数

故可以得出以下代码:

 let MPromise = function (excute) {            let status = 'pending'  // 初始化promise状态            let resolve = () => {                if (status == 'pending') {  // 不可逆原则,                    this.status = 'resolve'                }            }            let reject = () => {                if (status == 'pending') {                    this.status = 'reject'                }            }            excute(resolve, reject)        }        MPromise.prototype.then = function (resolve, reject) {  //在其原型链上绑定then函数            let self = this            if (self.status == 'resolve') {                resolve()            }            if (self.status == 'reject') {                reject()            }        }复制代码

调用我们的MPromise

 

        let p = new MPromise((res, rej) => {            console.log('start');            rej()            console.log('end');        })        p.then(function () {            console.log('then resolve');        }, function () {            console.log('then reject');        })复制代码

输出:


由此我们初步的promise原型已经完成。

2. 解决异步调用

      先看看原生Promise对异步事件的处理:

        let p2 = new Promise((res, rej) => {            console.log('befor');                        setTimeout(function(){                res()            })            console.log('after');                    })        p2.then(() => {            console.log('resolve then');        })复制代码

输出:

    befor

    after

    resolve then

而在上一步完成的MPromise没用加入异步事件的处理,在遇到异步事件时并不会执行res。

        let p = new MPromise((res, rej) => {            console.log('start');            setTimeout(function(){                res()            })            console.log('end');        })        p.then(function () {            console.log('then resolve');        }, function () {            console.log('then reject');        })复制代码

输出为: 

     start

     end

造成异步事件中的res没有执行的原因是由于js的事件机制造成的,异步事件会在同步事件执行完毕后才执行,也就是res()中改变thi.state是在then函数执行后再执行,所以造成了then在判断state的状态时无法正确处理。解决方法的主要思想是加入数组暂存,如下:

        let MPromise = function (excute) {            this.status = 'pending'            this.resolvArray = []            this.rejectArray = []            this.value = undefined            this.reason = undefined            let resolve = (value) => {                if (this.status == 'pending') {                    this.status = 'resolve'                    this.value = value                    this.resolvArray.forEach(fun => {  // 执行暂存中的函数                        fun()                    });                }            }            let reject = (reason) => {                if (this.status == 'pending') {                    this.reason = reason                    this.status = 'reject'                    this.rejectArray.forEach(fun => {                        fun()                    });                }            }            excute(resolve, reject)        }        MPromise.prototype.then = function (resolve, reject) {            let self = this            if (self.status == 'resolve') {                resolve(this.value)            }            if (self.status == 'reject') {                reject(this.reason)            }            if (self.status == 'pending') {   // 如果为pending则将resolve跟rejectpush到其对应暂存数组中                self.resolvArray.push(                    function () {                        resolve(self.value)                    })                self.rejectArray.push(                    function () {                        reject(self.reason)                    })            }        }复制代码

测试我们的MPromise

        let p = new MPromise((res, rej) => {            console.log('start');            setTimeout(function () {                res('param')            }, 2000)            console.log('end');        })        p.then(function (val) {            console.log('then resolve' + val);        }, function (val) {            console.log('then reject' + val);        }) 复制代码


3. 解决链式调用

    最后一步,promise最重要的作用:链式调用解决回调地狱。核心思想:在then中返回一个新的promise实例:

   MPromise.prototype.then = function (onResolve, onReject) {            let self = this            let p2 = new MPromise((resolve, reject) => {                if (self.status == 'resolve') {                    try {                        let x = onResolve(self.value)                        resolve(x) // 这是 x 是常量的时候,但x可能是一个新的promise,                    } catch (e) {                        reject(e)                    }                    // resolve(this.value)                }                if (self.status == 'reject') {                    try {                        let x = onReject(self.reason)                        resolve(x)                    } catch (e) {                        reject(e)                    }                }                if (self.status == 'pending') {                    self.resolvArray.push(                        function () {                            try {                                let x = onResolve(self.value)                                resolve(x)                            } catch (e) {                                reject(e)                            }                        })                    self.rejectArray.push(                        function () {                            try {                                let x = onReject(self.reason)                                resolve(x)                            } catch (e) {                                reject(e)                            }                        })                }            })            return p2        }复制代码

   测试我们的代码:

       let p = new MPromise((res, rej) => {            console.log('start');            // setTimeout(function () {                res('param')            // }, 2000)        })        let p2 = p.then(function (val) {            console.log('then resolve' + val);        }, function (val) {            console.log('then reject' + val);        })        p2.then((val)=>{            console.log('second then '+val);              },()=>{        }).then((val)=>{            console.log('three  then '+val);              },()=>{        })        console.log(p2);                console.log('end');复制代码

输出:

  start 

  end 

  then resolveparam 

  second then 

  three then 

结语

    promise的核心思想为如上的三步,理解后就很简单。


转载于:https://juejin.im/post/5d31cdab5188253e215ff87e

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值