手写实现一个自己的promise

6 篇文章 0 订阅
2 篇文章 0 订阅

实现内容:

        1、then方法:当resolve时会触发then方法

        2、catch方法:当reject时会触发catch方法

        3、promise.resolve():直接生成一个成功状态的promise对象

        4、promise.reject():直接生成一个失败状态的promise对象

        5、Promise.all():参数为promise对象数组,等待所有状态都不为pending

        6、Promise.race():参数为promise对象数组,运行最快的那一个触发then或catch

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>手写实现一个Promise</title>
</head>

<body>

</body>
<script type="text/javascript">
    function MyPromise(fn) {
        this.promiseState = 'pending';
        this.promiseResult = undefined;
        // 注册promise对象的任务函数
        this.thenCallback = undefined;
        this.catchCallback = undefined;
        // 为保证this指向,使用变量进行保存
        var _this = this;
        var resolve = function(resolveVal) {
            // 防止状态变更后,再次修改状态,promise状态一旦变更是不能回退的
            if (_this.promiseState === 'pending') {
                // 变更状态和值
                _this.promiseState = 'fulfilled';
                _this.promiseResult = resolveVal;
                // 用setTimeout模拟异步
                // 虽然resolve在then之前执行的
                // 但是该函数的回调一定是在Promise对象初始化完毕后执行的
                // 所以我们的回调执行时,thenCallback就已经初始化完毕了
                if (resolveVal instanceof MyPromise) {
                    // dang传入的resolveVal是一个promise对象时,就可以直接用then去进行处理
                    resolveVal.then(function(res) {
                        if (_this.thenCallback) {
                            // 此时调用then中注册的回调函数时,应该传入该对象then之后的结果
                            _this.thenCallback(res);
                        }
                    })
                } else {
                    setTimeout(function() {
                        if (_this.thenCallback) {
                            _this.thenCallback(resolveVal);
                        }
                    });
                }
            }

        };
        var reject = function(rejectVal) {
            // 防止状态变更后,再次修改状态,promise状态一旦变更是不能回退的
            if (_this.promiseState === 'pending') {
                // 变更状态和值
                _this.promiseState = 'rejected';
                _this.promiseResult = rejectVal;


                setTimeout(function() {
                    // 当只有catchCallback时,代表直接写的catch,直接触发流程即可
                    if (_this.catchCallback) {
                        _this.catchCallback(rejectVal);
                        // 如果如果没有catchCallback,存在thenCallback,代表peomise直接使用了then
                        // 此时应该先让then执行来进行本次then函数的跳过,直到找到catch
                    } else if (_this.thenCallback) {
                        _this.thenCallback(rejectVal);
                    } else {
                        throw ('notfind catch function')
                    }
                });
            }
        };

        if (fn) {
            fn(resolve, reject);
        } else {
            throw ('Promise resolver undefind is not a function')
        }
    }
    // 实现then和catch方法
    MyPromise.prototype.then = function(callback) {
        var _this = this;
        // 实现链式调用,需要return一个新的promise对象
        return new MyPromise(function(resolve, reject) {
            // 在then函数执行的时候,优先在函数内部注册回调函数任务
            // 等待resolve执行的时候,通过注册异步的任务赖在该回调后捕获它
            _this.thenCallback = function(val) {
                // catch的链式调用复杂,所以可能在catch触发的时候也会触发
                if (_this.promiseState == 'rejected') {
                    // 如果是reject触发的callback,直接调用下一个对象的reject
                    reject(val);
                } else {
                    var res = callback(val);
                    // 判断如果某一次then函数返回的是一个rejected的promise对象
                    // 此时我们需要在这里直接注册catch,并且在catch内部拿到对象的结果
                    // 然后通过下一个对象的reject链式通知最近的catch执行
                    if (res instanceof MyPromise && res.promiseState === 'rejected') {
                        res.catch(function(err) {
                            reject(err)
                        })
                    } else {
                        resolve(res);
                    }
                }

            }
        })

    }
    MyPromise.prototype.catch = function(callback) {
        var _this = this
        return new MyPromise(function(resolve, reject) {
            _this.catchCallback = function(val) {
                var res = callback(val);
                // catch本次对象的状态是reject,但是如果继续调用,默认触发的还是then
                resolve(res);
            }
        })
    }
    MyPromise.resolve = function(val) {
        return new MyPromise(function(resolve, reject) {
            resolve(val)
        })
    }
    MyPromise.reject = function(val) {
        return new MyPromise(function(resolve, reject) {
            reject(val)
        })
    }
    MyPromise.all = function(promiseArr) {
        var resArr = [];
        return new MyPromise(function(resolve, reject) {
            // MyPromise.all必须等待数组中所有的状态都不为pending才能往下触发
            promiseArr.forEach((promiseItem, index) => {
                promiseItem.then(function(res) {
                    resArr[index] = res;
                    let success = promiseArr.every(item => {
                        return item.promiseState === 'fulfilled';
                    })
                    if (success) {
                        resolve(resArr)
                    }
                }).catch(function name(err) {
                    reject(err)
                })
            });
        })
    }
    MyPromise.race = function(promiseArr) {
        return new MyPromise(function(resolve, reject) {
            // MyPromise.all必须等待数组中所有的状态都不为pending才能往下触发
            promiseArr.forEach((promiseItem, index) => {
                promiseItem.then(function(res) {
                    resolve(res);
                }).catch(function name(err) {
                    reject(err);
                })
            });
        })
    }


    // 示例5
    var pAll1 = new MyPromise(function(resolve, reject) {
        setTimeout(() => {
            reject('第一个')
        }, 1000);
    });
    var pAll2 = new MyPromise(function(resolve, reject) {
        setTimeout(() => {
            resolve('第二个')
        }, 300);
    });
    var pAll3 = new MyPromise(function(resolve, reject) {
        setTimeout(() => {
            resolve('第三个')
        }, 2000);
    });
    MyPromise.all([pAll2, pAll1, pAll3]).then(function(res) {
        console.log(res)
    }).catch(function(err) {
        console.error(err);
    });


    // 示例1
    var mp1 = new MyPromise(function(resolve, reject) {
        reject('reject的值')
    })
    mp1.then(function(res) {
        console.log(res);
        console.log('then执行');
    }).then(function(res) {
        console.log(res);
        console.log('then执行');
    }).then(function(res) {
        console.log(res);
        console.log('then执行');
    }).catch(function(err) {
        console.log(err);
        console.log('catch执行');
    })


    // 示例2
    var mp2 = new MyPromise(function(resolve) {
        setTimeout(() => {
            resolve('第一秒')
        }, 1000);
    }).then(function(res) {
        console.log(res);
        return new MyPromise(function(resolve) {
            setTimeout(() => {
                resolve('第二秒')
            }, 1000);
        })
    }).then(function(res) {
        console.log(res);
        return new MyPromise(function(resolve) {
            setTimeout(() => {
                resolve('第三秒')
            }, 1000);
        })
    }).then(function(res) {
        console.log(res);
    })


    // 示例3
    let MP3 = new MyPromise(function(resolve, reject) {
        // resolve('我是promise的值');
        resolve(new MyPromise(function(resolve1, reject1) {
            resolve1('初始传入的peomise对象')
        }));
    });
    MP3.then(function(res) {
        console.log(res);
        console.log('then触发')
        return 123;
    }).then(function(res) {
        console.log('第二个then触发');
        console.log(res);
        return new MyPromise(function(resolve, reject) {
            resolve('第二个then的值');
        })
    }).then(function(res) {
        console.log('第三个then触发');
        console.log(res);
    })

    // 示例4
    var mp4 = new MyPromise(function(resolve, reject) {
        resolve('第一步')
    })
    mp4.then(function(res) {
        console.log(res);
        console.log('第一个then');
        return MyPromise.reject('中断');
    }).then(function(res) {
        console.log(res);
        console.log('第二个then');
        return 3
    }).then(function(res) {
        console.log(res);
        console.log('第三个then');
        return 4
    }).catch(function(err) {
        console.log(err);
        console.log('catch执行');
    })
</script>

</html>

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值