简单实现一个promise,理解其原理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>

    // 添加状态
    const PENDING = 'pending';
    const FULFILLED = 'fulfilled';
    const REJECTED = 'rejected';

    // 自主实现一个promise
    function MyPromise(executor) {

        let self = this;
        self.state = PENDING; // 刚进入时进行等待状态

        self.state = PENDING;
        self.value = null;
        self.reason = null;
        self.onFulfilledCallbacks = []; // 异步调用时,为了保证then方法依然能正常回调,增加回调函数,之所以是数组的形式,是同一个实例对象可以有多个then的方法调用
        self.onRejectedCallbacks = []; // 异步调用时,为了保证then方法依然能正常回调,增加回调函数

        function resolve(value) {
            // 进入该方法时,如果依然是等待的状态,则将状态修改为已完成
            if (self.state === PENDING) {
                self.state = FULFILLED;
                self.value = value;
            }

            // 执行回调函数
            self.onFulfilledCallbacks.forEach(function(fulfilledCallback) {
                fulfilledCallback();
            });
        }

        function reject(reason) {
            // 进入该方法时,如果依然是等待的状态,则将状态修改为已拒绝
            if (self.state === PENDING) {
                self.state = REJECTED;
                self.reason = reason;
            }

            // 执行回调函数
            self.onRejectedCallbacks.forEach(function(rejectedCallback) {
                rejectedCallback();
            });
        }

        try {
            executor(resolve, reject);
        } catch (reason) {
            reject(reason);
        }
    }


    // 实现promise的链式调用,增加一个resolvePromise的方法
    MyPromise.prototype.resolvePromise = function(promise2, x, resolve, reject) {
        /*
        * promise2---then方法当中实例的promise对象,会在then方法中进行返回
        * x---是上一个promise当中的返回值
        * resolve----promise2实例化方法的成功回调函数
        * reject---promise2实例化方法的失败回调函数
        * */
        let self = this;
        let called = false;   // called 防止多次调用

        if (promise2 === x) {
            return reject(new TypeError('循环引用'));
        }

        if (x !== null && (Object.prototype.toString.call(x) === '[object Object]' || Object.prototype.toString.call(x) === '[object Function]')) {
            // x是对象或者函数
            try {
                let then = x.then;

                if (typeof then === 'function') {
                    // 如果是函数的话,则代表是promise,使用call,将then的方法修改为X这个promise函数,让原本第2个promise中的then执行,去运行它本身
                    then.call(x, (y) => {
                        // 别人的Promise的then方法可能设置了getter等,使用called防止多次调用then方法
                        if (called) return ;
                        called = true;
                        // 成功值y有可能还是promise或者是具有then方法等,再次resolvePromise,直到成功值为基本类型或者非thenable
                        self.resolvePromise(promise2, y, resolve, reject);
                    }, (reason) => {
                        if (called) return ;
                        called = true;
                        reject(reason);
                    });
                } else {
                    if (called) return ;
                    called = true;
                    resolve(x);
                }
            } catch (reason) {
                if (called) return ;
                called = true;
                reject(reason);
            }
        } else {
            // x是普通值,直接resolve
            resolve(x);
        }
    };


    // 添加.then方法,接收两个函数 onFulfilled 和 onRejected,分别作为Promise成功和失败的回调。所以,在then方法中我们需要对状态state进行判断,如果是fulfilled,则执行onFulfilled(value)方法,如果是rejected,则执行onRejected(reason)方法。
    MyPromise.prototype.then = function(onFuifilled, onRejected) {
        let self = this;

        // promise中可以连续调用,并且会将上一个promise中得到的值,传递到下一个promise的函数中,所有需要实例化多一个promise
        let promise2 = null;

        promise2 = new MyPromise((resolve, reject) => {
            // 注意这里self其实是外层的promise,并且虽然是不同的实例对象,但是有原型继承的关系,所以这个promise2也可以使用then
            if (self.state === PENDING) {
                self.onFulfilledCallbacks.push(() => {
                    // promise实际属于微任务,使用setTimeout是实现promise中异步执行
                    setTimeout(()=>{
                        try {
                            // 这里调用的onFuifilled是上个promise中的函数,所以能得到上一个promise的返回值
                            let x = onFuifilled(self.value);
                            // 将promise2与上一个promise得到的值作为参数传递,这里注意resolve与reject是promise2实例对象的回调函数
                            self.resolvePromise(promise2, x, resolve, reject);
                        } catch(reason) {
                            reject(reason);
                        }
                    },0)

                });
                self.onRejectedCallbacks.push(() => {
                    setTimeout(()=>{
                        try {
                            let x = onRejected(self.reason);
                            self.resolvePromise(promise2, x, resolve, reject);
                        } catch(reason) {
                            reject(reason);
                        }
                    },0)

                });
            }

            if (self.state === FULFILLED) {
                setTimeout(()=>{
                    try {
                        let x = onFuifilled(self.value);
                        self.resolvePromise(promise2, x, resolve, reject);
                    } catch (reason) {
                        reject(reason);
                    }
                },0)
            }

            if (self.state === REJECTED) {
                setTimeout(()=>{
                    try {
                        let x = onRejected(self.reason);
                        self.resolvePromise(promise2, x, resolve, reject);
                    } catch (reason) {
                        reject(reason);
                    }
                },0)

            }
        });

        return promise2;
    };

    let promise = new MyPromise(function(resolve, reject) {
        resolve(123);
    })

    promise.then(function(value) {
        console.log('value', value);
        return value + 1;
    }, function(reason) {
        // console.log('reason', reason);
    })
        .then(function(v){
        console.log(v);
    },function(){})

    /*输出结果为 123 , 124
    *
    * */


</script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值