JavaScript面试必考之实现手写Promise

Promise手写

Promise作为面试必考题,Promise的手写也是面试官必问的问题,所以对于Promise我们一定要了解透彻

框架

(function(window) {
    
    MyPromise.prototype.then = function (onResolved, onRejected) {}
    MyPromise.prototype.catch = function (onRejected) {}
    
    function MyPromise(executor){

        function resolve(value){}

        function reject(error){}

        try{
            executor(resolve, reject)
        }catch(error){
            reject(error)
        }
    }

    window.MyPromise = MyPromise
}(window))

完整代码

    (function (window) {
        //将.then,.catch方法挂载在MyPromise原型上
        MyPromise.prototype.then = function (onResolved, onRejected) {//.then接受两个回调函数,resolved状态和rejeced状态

            // .then返回一个promise对象
            return new MyPromise((resolve, reject) => {
                let self = this;

                if (self.status === 'pending') {//如果MyPromise状态为pending,将两个回调函数push进回调数组中等待

                    this.callbacks.push({ onResolved, onRejected })

                } else if (self.status === 'resolved') {  //如果MyPromise状态为resolved,将onResolved直接调用
                    setTimeout(() => {
                        //检查.then中的回调有没有return返回值
                        const result = onResolved(self.data)

                        //如果没有return返回值,默认返回promise对象
                        if (result instanceof MyPromise) {
                            result.then((res => resolve(res), err => reject(err)))
                            return result
                        } else {
                            resolve(result)
                        }
                    })
                } else {

                    setTimeout(() => {
                        onResolved(self.data)
                    })
                }
            })

        }
        MyPromise.prototype.catch = function (onRejected) { //.catch接受一个回调函数

            if (this.status === 'pending') {
                // 将回调函数放入callbacks数组中
                this.callbacks.push({ onRejected })
            } else if (this.status === 'rejected') {
                setTimeout(() => {
                    onRejected(this.data)
                })

            }
        }

        // MyPromise构造函数接受一个执行函数
        function MyPromise(executor) {
            const self = this;
            self.data = undefined;
            self.callbacks = []
            //设置promise对象初始状态为pending
            self.status = 'pending'
            //执行函数第一个参数为resolve回调
            function resolve(value) {
                //如果状态不是pending,则直接返回
                if (self.status !== 'pending') {
                    return
                }

                // 执行resolve,promise对象状态变更
                self.status = 'resolved';

                // 拿到resolve中的值
                self.data = value;

                // 调用callbacks中的回调函数
                if (self.callbacks.length > 0) {
                    setTimeout(() => {
                        self.callbacks.forEach(callbacksObj => {
                            callbacksObj.onResolved(value)
                        });
                    })
                }
            }

            // 执行函数第二个参数为rejecr回调
            function reject(error) {
                //如果状态不是pending,则直接返回
                if (self.status !== 'pending') {
                    return
                }

                // 执行resolve,promise对象状态变更
                self.status = 'rejected';

                // 拿到resolve中的值
                self.data = error;

                // 调用callbacks中的回调函数
                if (self.callbacks.length > 0) {
                    setTimeout(() => {
                        self.callbacks.forEach(callbacksObj => {
                            callbacksObj.onRejected(value)
                        });
                    })
                }
            }
            //使用try catch捕获错误
            try {
                // 在try内执行执行函数
                executor(resolve, reject)
            } catch (error) {
                // 如果出错,默认执行reject
                reject(error);
            }

        }

        window.MyPromise = MyPromise
    }(window))

测试

resolve

    let MyPromiseTest = new MyPromise((resolve, reject) => {
        resolve('resolve')
    })
    MyPromiseTest.then(res => {
        console.log(res);
    })
    
    //   resolve
    let MyPromiseTest = new MyPromise((resolve, reject) => {
        resolve('resolve');
    })
    MyPromiseTest.then(res => {
        console.log(res);

    })
        .then(res => {
            console.log('我是.then()后面的.then()');
        })
        
    //   resolve
    //   我是.then()后面的.then()

reject

    let MyPromiseTest = new MyPromise((resolve, reject) => {
        reject('reject')
    })
    MyPromiseTest.catch(err => {
        console.log(err);
    })
    
    //   reject
    let MyPromiseTest = new MyPromise((resolve, reject) => {
        console.log(a);
    })
    MyPromiseTest.catch(err => {
        console.log('捕获错误' + ':' + err);
    })
    
    //   捕获错误:ReferenceError: a is not defined

原文地址:https://juejin.cn/post/7152725416040464421