面试题:手撕PromiseA+规范 (核心功能)

注释应该还可以:

(function () {
    // 开启严格模式
    "use strict"

    function Promise(executor) {
        var self = this,
            change;

        // 传进来的参数不是function 直接报错
        if (typeof executor !== 'function') throw new TypeError(`${executor} must be an function`);
        // 不能通过call/apply/bind 改变this ,this不是promise的实例 直接报错
        if (!(self instanceof Promise)) throw new TypeError('undefined is not a promise');

        // promise 状态  默认等待状态
        self.state = 'padding';
        // promise 结果  默认undefined
        self.result = undefined;
        // 成功回调数组
        self.onfufiledCallback = [];
        // 失败回调数组
        self.onrejectedCallback = [];

        change = function change(state, result) {
            // 判断当前promise是否为padding状态,状态一旦修改就不能再修改
            if (self.state !== 'padding') return;
            self.state = state;
            self.result = result;

            // 判断一下当前成功回调数组、失败回调数组 中是否存在待执行的方法,存在状态修改的时候拿出来执行
            var callbacks = state === 'success' ? self.onfufiledCallback : self.onrejectedCallback,
                len = callbacks.length,
                i = 0,
                callback;
            for (; i < len; i++) {
                callback = callbacks[i];
                if (typeof callback === 'function') callback(result);
            }

        }
        try {
            // 同步代码执行
            executor(function resolve(result) {
                change('success', result)
            }, function reject(resaon) {
                change('fail', resaon)
            })
        } catch (error) {
            // 程序报错 promise状态也为失败
            change('fail', error)
        }

    }

    // 判断是否为类promise ,有.then方法返回true
    function isPromise(x) {
        if (x == null) return false;
        if (/^('object'|'function')$/i.test(typeof x)) {
            if (typeof x.then === 'function') {
                return true;
            }
        }
        return false;
    }

    // 统一返回处理结果
    function handler(promiseNew, x, resolve, reject) {
        if (promiseNew === x) throw new TypeError('Chaining cycle detected for promise #<Promise>');
        if (isPromise(x)) {
            try {
                // 实现then链
                x.then(resolve, reject)
            } catch (err) {
                reject(err)
            }
        }
        resolve(x)

    }
    // promise原型上成功方法
    Promise.resolve = function resolve(result) {
        return new Promise(function (resolve) {
            resolve(result)
        })
    }
    // promise原型上失败方法
    Promise.reject = function reject(reason) {
        return new Promise(function (_, reject) {
            reject(reason)
        })
    }
    Promise.all = function all(ary) {
        var newPromise,
            results = [],
            n = 0;

        // 判断传进来的参数不是数组 抛出异常
        if (!Array.isArray(ary)) throw new TypeError(`${ary} is not iterable`);
        // 处理promise数组
        ary.map(item => {
            // 判断当前项不是promise 默认返回一个成功的promise
            if (!isPromise(item)) {
                Promise.resolve(item);
            }
            return item;
        })

        // .all执行返回的新promise实例
        newPromise = new Promise(function (resolve, reject) {
            ary.forEach((promise, index) => {
                promise.then(function (result) {
                    n++;
                    // 使用index方式不用push往数组中放 是为了保证results中的返回结果跟传进来的结果保持一致
                    results[index] = result;
                    // 全部处理成功
                    if (n >= ary.length) resolve(results);

                }).catch(function (reason) {
                    reject(reason)
                })
            })
        })
        return newPromise;

    }
    // 原型重定向
    Promise.prototype = {
        then: function then(onfufiled, onrejected) {
            let self = this,
                promiseNew,
                x;
            // onfufiled, onrejected 不是方法默认 给他设置一个方法
            // 只传一个参数的时候 默认给他设置一个参数, 是为了加上穿透性
            if (typeof onfufiled !== "function") {
                onfufiled = function onfufiled(result) {
                    return result;
                };
            }

            if (typeof onrejected !== "function") {
                onrejected = function onrejected(reason) {
                    throw reason;
                };
            }
            // .then方法 返回值若是一个promise实例 则状态为返回的promise的状态
            // 返回值若不是一个promise实例 则代码执行不报错即为成功
            // 统一处理.then逻辑
            promiseNew = new Promise(function (resolve, reject) {
                switch (self.state) {
                    case 'success':
                        setTimeout(function () {
                            // 成功 失败统一处理
                            // 如果代码执行异常  返回的promise实例状态直接变为失败
                            try {
                                x = onfufiled(self.result);
                                handler(promiseNew, x, resolve, reject);
                            } catch (err) {
                                reject(err)
                            }
                        }, 0)
                        break;
                    case 'fail':
                        setTimeout(function () {
                            // 成功 失败统一处理
                            // 如果代码执行异常  返回的promise实例状态直接变为失败
                            try {
                                x = onrejected(self.result);
                                handler(promiseNew, x, resolve, reject);
                            } catch (err) {
                                reject(err)
                            }
                        }, 0)
                        break;
                    default:
                        // promise为padding状态是需要将onfufiled, onrejected存起来
                        // 待promise状态修改时执行
                        // 利用 柯理化函数的思想,在函数外边包一层 预处理的方式拿到函数执行返回结果
                        self.onfufiledCallback.push(function (result) {
                            try {
                                x = onfufiled(result);
                                handler(promiseNew, x, resolve, reject);
                            } catch (err) {
                                reject(err);
                            }
                        });
                        self.onrejectedCallback.push(function (result) {
                            try {
                                x = onrejected(result);
                                handle(promiseNew, x, resolve, reject);
                            } catch (err) {
                                reject(err)
                            }
                        });
                    // self.onfufiledCallback.push(function (resaon) {
                    //     try {
                    //         x = onrejected(result);
                    //         handler(promiseNew, x, resolve, reject);
                    //     } catch (err) {
                    //         reject(err);
                    //     }
                    // });

                }
            })
            return promiseNew;

        },
        catch: function (rejected) {
            return this.then(null, rejected)
        },
        finally: function () {

        }
    }
    // 判断是否为浏览器环境下
    if (typeof window !== 'undefined') window.Promise = Promise;
    // 判断是否支持commonJS规范
    if (typeof modules === 'object' && modules.exports === 'object') modules.exports = Promise

})();

// 测试代码
var a = Promise.resolve('11111')
var b = Promise.reject('6666')
// a.then(result => {
//     console.log(result);
// }, reason => {
//     console.log(reason);
// }).then(result => {
//     console.log('8765432');
// });
// b.then(null, reason => {
//     console.log(reason)
// })
Promise.all([a, b])
    .then(result => {
        console.log(result);
    }).catch(function (res) {
        console.log(res);
    });
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值