JS 手写promise 实现


 function MyPromise (execute) {
     // value 记录异步任务成功的执行结果
     this.value = null;
      // reason 记录异步任务失败的执行结果
     this.reason = null;
     // status 记录当前状态,初始化pending
     this.status = 'pending';

     this.onResolvedQueue = [];
     this.onRejectedQueue = [];

     let self = this;

     function resolve(value) {
         if(self.status !== 'pending' ) {
            return
         }
         // 异步任务成功,把结果赋值给value
         self.value = value;
         // 把当前状态切换为resolved
         self.status = 'resolved';

         self.onResolvedQueue.forEach(resolved => resolved(self.value))
     }

     function reject(reason) {
        if(self.status !== 'pending' ) {
            return
         }
        // 异步任务失败,把结果赋值给value
        self.reason = reason;
         // 把当前状态切换为rejected
        self.status = 'rejected';

        self.onRejectedQueue.forEach(rejected => rejected(self.reason))
    }

    // 把resolve和reject能力 赋予执行器
    try {
        execute(resolve, reject);

    }catch(e) {
        reject(e)
    }

}

// then方法接受两个函数作为入参(可选)
MyPromise.prototype.then = function (onResolved, onRejected) {
    // 注意, onResolved 和 onRejected  必须是函数; 如果不是,我们此处用一个透传来兜底
    if(typeof onResolved !== 'function') {
        onResolved = function(x) {return x};
    }
    if(typeof onRejected !== 'function') {
        onRejected = function(e) {throw e};
    }
    let self = this;
    // 保存返回值x
    let x = null;

    // resolve 状态处理函数
    function resolveByStatus(resolve, reject) {
        // 包装成异步, 确保在then后执行
        setTimeout(() => {
            try {
                x = onResolved(self.value)
                resolutionProcedure(promise2, x, resolve, reject);
            } catch(e) {
                reject(e)
            }
        })
    }

    // reject 状态处理函数
    function rejectByStatus(resolve, reject) {
        setTimeout(() => {
            try {
                x = onRejected(self.reason)
                resolutionProcedure(promise2, x, resolve, reject);
            } catch(e) {
                reject(e)
            }
        })
    }

    let promise2 = new MyPromise((resolve, reject) => {
        // 判断是否是resolved状态
        if(self.status === 'resolved') {
            // 如果是 执行对应的处理方法
            resolveByStatus(resolve, reject)
        } else if(self.status === 'rejected') {
            // 若是rejected 状态, 则执行rejected 对应方法
            rejectByStatus(resolve, reject)
        } else if(self.status === 'pending') {
            self.onResolvedQueue.push(() => resolveByStatus(resolve, reject))
            self.onRejectedQueue.push(() => rejectByStatus(resolve, reject))
        }
    })
    return promise2;
}


function resolutionProcedure(promise2, x, resolve, reject) {
    // 不被重复执行
    let hasCalled = null;

    if(x === promise2) {
        return reject(new TypeError('循环引用'))
    } else if((typeof x === 'object'&& x !== null) || typeof x === 'function') {
        try {
            let then = x.then;
            if(typeof then === 'function') {
                then.call(x, (y) => {
                    if( hasCalled ) return
                    hasCalled = true;

                    resolutionProcedure(promise2, y, resolve, reject);
                }, (err) => {
                    if( hasCalled ) return
                    hasCalled = true;
                    reject(err)
                })
            } else {
                // 如果then不是function, 则x为参数执行promise
                resolve(x);
            }

        } catch(e) {
            if( hasCalled ) return
            hasCalled = true;
            reject(err)
        }

    } else {
        // 如果x不是object或者function, 则x为参数执行promise
        resolve(x);
    }

}

let promise2 = new MyPromise(function(resolve, reject) {
// let MyPromise = new Promise(function(resolve, reject) {
    resolve('成了');
  
})
promise2.then((value) => {
    console.log('value:', value, '第一个任务')
    return '我第一个个任务传递过来的'
}).then((value) => {
    console.log('第二个任务', value)
})

  


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM