如何应对面试官的手写Promise!!!

Promise是处理异步编码的一个解决方案,在Promise出现以前,异步代码的编写都是通过回调函数来处理的,回调函数本身没有任何问题,只是当多次异步回调有逻辑关系时就会变得复杂:

const fs = require('fs');
fs.readFile('1.doc', (err,res) => {
    fs.readFile('2.doc', (err,res) => {
        fs.readFile('3.doc', (err,res) => {
            // 可能还有后续代码...
        });
    });
});

不过Promise的横空出世就有效的解决了这一问题,也就是回调地狱问题;

​ 而手写Promise也是最近几年面试很容易考到的问题,下面收集了简易版的Promise和合乎Promises/A+规范的Promise,仅供参考!

一、简易版

1、首先定义constructor
constructor(fn) {
        // 定义Promise的三种状态
        this.statusObj = {
            PENDING: 'PENDING',
            RESOLVED: 'RESOLVED',
            REJECTED: 'REJECTED'
        }

        this.value = null;// 定义传递给then的value
        this.status = this.statusObj.PENDING; // 设置当前Promise的状态
        this.resolvedCallBacks = []; // 定义Promise成功状态的回调函数集合
        this.rejectedCallBacks = []; // 定义Promise失败状态的回调函数集合
        MyPromise.that = this; // 为静态方法定义其内部可以使用的指向实例的that
        try {
            // 执行new Promise() 内传入的方法
            fn(MyPromise.resolve, MyPromise.reject);
        } catch (error) {
            MyPromise.reject(this.value);
        }
    }
2、完善resolve、reject、then方法
    /**
     * 静态resolve方法,MyPromise实例不可访问;
     * 支持类MyPromise访问,例:MyPromise.resolve('success').then(e=>e)
     * @param value 
     */
    static resolve(value) {
        const that = MyPromise.that; // 由于静态方法内的this访问的是类还不是实例,所以使用这种办法访问对象实例
        const f = that instanceof MyPromise; // 确认是否是MyPromise实例访问resolve
        // MyPromise 实例访问resolve,如果访问成功 状态改变、值改变
        if (f && that.status === that.statusObj.PENDING) {
            that.status = that.statusObj.RESOLVED;
            that.value = value;
            that.resolvedCallBacks.map(cb => that.value = cb(that.value));
        }

        // MyPromise 类访问resolve
        if (!f) {
            const obj = new MyPromise();
            return Object.assign(obj, {
                status: obj.statusObj.RESOLVED,
                value
            })
        }
    }

​ 那么resolve方法就和resolve方法差不多

    /**
     * 静态resolve方法
     * @param value 
     */
    static reject(value) {
        const that = MyPromise.that;
        const f = that instanceof MyPromise;
        if (f && that.status === that.statusObj.REJECTED) {
            that.status = that.statusObj.REJECTED;
            that.value = value;
            that.rejectedCallBacks.map(cb => that.value = cb(that.value));
        }
        if (!f) {
            const obj = new MyPromise();
            return Object.assign(obj, {
                status: that.statusObj.REJECTED,
                value
            })
        }
    }

最后是then方法

    /**
     * MyPromise 原型上的then方法
     * @param onFulfilled 
     * @param onRejected 
     */
    then(onFulfilled, onRejected) {
        const { PENDING, RESOLVED, REJECTED } = this.statusObj;
        const f = typeof onFulfilled == 'function' ? onFulfilled : c => c
        const r = typeof onRejected == 'function' ? onRejected : c => { throw c };
        switch (this.status) {
            case PENDING: // PENDING 状态下 向下回调函数结合添加callback
                this.resolvedCallBacks.push(f);
                this.rejectedCallBacks.push(r);
                break;
            case RESOLVED:
                this.value = f(this.value); // 将回调函数的返回值赋值给实例的 value ,满足链式调用then方法时传递value
                break;
            case REJECTED:
                this.value = r(this.value); // 将回调函数的返回值赋值给实例的 value ,满足链式调用then方法时传递value
                break;
            default:
                break;
        }
        // 满足链式调用then,返回MyPromise实例对象
        return this
    }

至此呢,我们自定的MyPromise方法就写完了 ,接下里就是测试环节

// new 一个Promise进行测试
MyPromise.resolve('success').then((e) => {
    console.log(e);
    return e + 1;
}).then((res) => {
    console.log(res);
});

new MyPromise(resolve => {
    setTimeout(() => {
        resolve(1)
    }, 2000);
})
    .then((res2) => {
        console.log(res2);
        return 2;
    }).then((res3) => {
        console.log(res3);
    })

下面是测试的结果。
在这里插入图片描述
完整版代码:

class MyPromise {
    constructor(fn) {
        // 定义Promise的三种状态
        this.statusObj = {
            PENDING: 'PENDING',
            RESOLVED: 'RESOLVED',
            REJECTED: 'REJECTED'
        }

        this.value = null;// 定义传递给then的value
        this.status = this.statusObj.PENDING; // 设置当前Promise的状态
        this.resolvedCallBacks = []; // 定义Promise成功状态的回调函数集合
        this.rejectedCallBacks = []; // 定义Promise失败状态的回调函数集合
        MyPromise.that = this; // 为静态方法定义其内部可以使用的指向实例的that
        try {
            // 执行new Promise() 内传入的方法
            fn(MyPromise.resolve, MyPromise.reject);
        } catch (error) {
            MyPromise.reject(this.value);
        }
    }
    /**
     * 静态resolve方法,MyPromise实例不可访问;
     * 支持类MyPromise访问,例:MyPromise.resolve('success').then(e=>e)
     * @param value 
     */
    static resolve(value) {
        const that = MyPromise.that; // 由于静态方法内的this访问的是类还不是实例,所以使用这种办法访问对象实例
        const f = that instanceof MyPromise; // 确认是否是MyPromise实例访问resolve
        // MyPromise 实例访问resolve,如果访问成功 状态改变、值改变
        if (f && that.status === that.statusObj.PENDING) {
            that.status = that.statusObj.RESOLVED;
            that.value = value;
            that.resolvedCallBacks.map(cb => that.value = cb(that.value));
        }

        // MyPromise 类访问resolve
        if (!f) {
            const obj = new MyPromise();
            return Object.assign(obj, {
                status: obj.statusObj.RESOLVED,
                value
            })
        }
    }
    /**
     * 静态resolve方法
     * @param value 
     */
    static reject(value) {
        const that = MyPromise.that;
        const f = that instanceof MyPromise;
        if (f && that.status === that.statusObj.REJECTED) {
            that.status = that.statusObj.REJECTED;
            that.value = value;
            that.rejectedCallBacks.map(cb => that.value = cb(that.value));
        }
        if (!f) {
            const obj = new MyPromise();
            return Object.assign(obj, {
                status: that.statusObj.REJECTED,
                value
            })
        }
    }
    /**
     * MyPromise 原型上的then方法
     * @param onFulfilled 
     * @param onRejected 
     */
    then(onFulfilled, onRejected) {
        const { PENDING, RESOLVED, REJECTED } = this.statusObj;
        const f = typeof onFulfilled == 'function' ? onFulfilled : c => c
        const r = typeof onRejected == 'function' ? onRejected : c => { throw c };
        switch (this.status) {
            case PENDING: // PENDING 状态下 向下回调函数结合添加callback
                this.resolvedCallBacks.push(f);
                this.rejectedCallBacks.push(r);
                break;
            case RESOLVED:
                this.value = f(this.value); // 将回调函数的返回值赋值给实例的 value ,满足链式调用then方法时传递value
                break;
            case REJECTED:
                this.value = r(this.value); // 将回调函数的返回值赋值给实例的 value ,满足链式调用then方法时传递value
                break;
            default:
                break;
        }
        // 满足链式调用then,返回MyPromise实例对象
        return this
    }
}
// new 一个Promise进行测试
MyPromise.resolve('success').then((e) => {
    console.log(e);
    return e + 1;
}).then((res) => {
    console.log(res);
});

new MyPromise(resolve => {
    setTimeout(() => {
        resolve(1)
    }, 2000);
})
    .then((res2) => {
        console.log(res2);
        return 2;
    }).then((res3) => {
        console.log(res3);
    })

那么合乎Promises/A+规范的Promise后续收集到了再添加进去吧。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值