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

    正文概述 掘金(我是一个小菜鸡)   2021-03-30   556

    什么是Promise

    Promise对象是JavaScript异步操作解决方案,为异步操作提供统一接口。Promise可以让异步操作写起来,就像在写同步操作的流程,而不必一层层的嵌套回调函数。就是我们所说的回调地狱。

    怎么实现一个Promise?

    第一部分

    实现之前我们先了解下它的一些特点,结合这些特点我们实现起来会比较容易理解一点。

    1. 有三种状态,默认是pending,成功为fulfilled,失败为rejected
    2. 创建时必须传递一个函数,不然会报错
    3. 传递函数中参数是两个回调函数,resolve和reject
    4. 状态一旦发生改变就不会发生变化

    特点很多我们先按照这些特点慢慢实现

    class MyPromise{
        constructor(fn) {
            // 2:promise接收的必须是个函数,不然报错
            if (!this.isFunc(fn)){
                throw new Error('这不是个函数')
            }
            // 1:定义默认状态
            this.status = 'pending'
    
            //3:函数参数中有两个回调参数;resolve和reject
            this.resolve = (data) =>{
                //状态一旦发生改变就不会在改变,所以在这里判断下是否为默认状态
                if (this.status === 'pending'){
                    this.status = 'fulfilled'
                }
            }
    
            this.reject = (data) =>{
                if (this.status === 'pending'){
                    this.status = 'rejected'
                }
            }
            fn(this.resolve,this.reject)
        }
        // 首先定义个方法判断是否为函数
        isFunc(fn){
            return typeof fn === 'function'
        }
    }
    let a = new MyPromise(function (resolve,reject){
        resolve()
        console.log('执行了');
    })
    console.log(a);
    

    看下执行结果,状态已经是成功了

    Promise:手撕Promise

    第二部分

    再说说还有的特点

    1. 同一个promise对象可以添加多个then监听,状态改变时会按照监听顺序依次执行
    2. then方法每次执行完毕会返回一个新的promise对象
    3. 上一个Promise对象的then方法可以给返回的新的Promise的then传递参数
    4. 无论上一个是在then成功或者失败的回调中传参,都会传递给新的Promise对象then方法中成功的回调
    5. 如果上一个传递的是一个Promise对象,那么传给下一个的成功还是失败由传递的Promsie状态决定  

    代码块有点问题,放个图片

    Promise:手撕Promise

    看下运行结果:

    Promise:手撕Promise

    这里难理解的可能就是对then return的值进行判断,因为下个promise会继承上一个promise的状态,因为如果then中return的是一个promise对象的话,下一个promise的状态就是按照这个return过来的。

    第三部分

    最后一点了。也是上面的基础上的补充

    1.   then返回的promise可以捕捉当前then方法中的异常

    2. catch方法就是then方法的语法糖

    多余的注释我就先去掉了,下面就是完整版的了

    class MyPromise{
        constructor(fn) {
            if (!this.isFunc(fn)){
                throw new Error('这不是个函数')
            }
            this.status = 'pending'
            //定义两个属性保存resolve和reject中的参数
            this.value = undefined
            // 存放成功的数组
            this.onSuccessCallbacks = []
            this.fail = undefined
            // 存放失败的数组
            this.onFailCallbacks = []
            //函数参数中有两个回调参数;resolve和reject
            this.resolve = (data) =>{
                //状态一旦发生改变就不会在改变,所以在这里判断下是否为默认状态
                if (this.status === 'pending'){
                    this.status = 'fulfilled'
                    this.value = data
                    if (this.onSuccessCallbacks){
                        this.onSuccessCallbacks.forEach((fn) => {
                            fn(this.value)
                        })
                    }
                }
            }
            this.reject = (data) =>{
                if (this.status === 'pending'){
                    this.status = 'rejected'
                    this.fail = data
                    if (this.onFailCallbacks){
                        this.onFailCallbacks.forEach((fn) => {
                            fn(this.fail)
                        })
                    }
                }
            }
            fn(this.resolve,this.reject)
        }
        then(onSuccess,onFail){
            return new MyPromise((nextSuccess,nextFail) => {
                //then返回的promise可以捕捉当前then方法中的异常
                // 所以我们可以利用try catch来捕获异常
                try {
                    if (this.isFunc(onSuccess)){
                        if (this.status === 'fulfilled'){
                            let res = onSuccess(this.value)
                            if (res instanceof MyPromise){
                                res.then(nextSuccess,nextFail)
                            }else if (res !== undefined){
                                nextSuccess(res)
                            }else {
                                nextSuccess()
                            }
                        }
                    }
                    // 将异常信息传递给下一个promise失败的回调
                }catch (e) {
                    nextFail(e)
                }
                try {
                    if (this.isFunc(onFail)){
                        if (this.status === 'rejected'){
                            let res = onFail(this.fail)
                            if (res instanceof MyPromise){
                                res.then(nextSuccess,nextFail)
                            }else if (res !== undefined){
                                nextSuccess(res)
                            }else {
                                nextFail()
                            }
                        }
                        //这里要加个判断,因为我们有时写的话可能会省略then中失败的回调,利用catch捕获
                    }else if (onFail === undefined){
                        if (this.fail){
                            nextFail(this.fail)
                        }
                    }
                }catch (e) {
                    nextFail(e)
                }
                // 解决延迟回调的问题
                if (this.status === "pending"){
                    if (this.isFunc(onSuccess)){
                        this.onSuccessCallbacks.push(() => {
                            try {
                                let res = onSuccess(this.value)
                                if (res instanceof MyPromise){
                                    res.then(nextSuccess,nextFail)
                                }else if (res !== undefined){
                                    nextSuccess(res)
                                }else {
                                    nextSuccess()
                                }
                            }catch (e) {
                                nextFail(e)
                            }
                        })
                    }
                    if (this.isFunc(onFail)){
                        this.onFailCallbacks.push(() => {
                            try {
                                let res = onFail(this.fail)
                                if (res instanceof MyPromise){
                                    res.then(nextSuccess,nextFail)
                                }else if (res !== undefined){
                                    nextSuccess(res)
                                }else {
                                    nextFail()
                                }
                            }catch (e) {
                                nextFail(e)
                            }
                        })
                    }else if (onFail === undefined){
                        this.onFailCallbacks.push(nextFail)
                    }
                }
            })
        }
        // catch可以看作是then的一个语法糖
        catch(onFail){
            return this.then(undefined , onFail)
        }
        // 首先定义个方法判断是否为函数
        isFunc(fn){
            return typeof fn === 'function'
        }
    }
    let a = new MyPromise(function (resolve,reject){
        resolve('xyz')
        // reject('xyz')
        console.log('执行了');
    })
    let b = a.then(function (data) {
        console.log(data,'成功');
        xxx
    })
    b.then(function (data) {
        console.log(data);
    },function (data) {
        console.log(data,'sss');
    })
    

      看下执行结果

    Promise:手撕Promise

    这里下一个promise成功捕捉到了上一个then中的错误

    Promise的其他方法

    all方法

    Promise的all方法接收一个数组,数组中存放promise对象,只有数组中的promise都成功了才会执行then方法,并且会按照添加的顺序,将所有成功的结果重新打包到一个数组中返回给我们,如果有一个失败就会立即执行失败的回调。

    要么一起成功,要么一起失败

    //因为all是一个静态方法
    static all(list){
        //因为返回的是一个数组,所以先定义一个
        let arr = []
        return new MyPromise((resolve,reject) => {
            list.forEach((value) => {
                value.then((data) => {
                    arr.push(data)
                },(error) =>{
                    reject(error)
                })
            })
            resolve(arr)
        })
    }
    

      

    race方法

    Promise的race方法接收一个数组,数组中存放promise对象。不过它取决于数组中第一个promise的状态

    // race 也是个静态方法
    static race(list){
        return new MyPromise((resolve,reject)=>{
            list.forEach((value) => {
                value.then(function (data) {
                    resolve(data)
                },function (error) {
                    reject(error)
                })
            })
        })
    }
    

    总结

    我表达的可能不是太好,不太容易理解,也可能有错误的地方我没检查出来。希望大家多多包含?


    起源地下载网 » Promise:手撕Promise

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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