Promise续(尝试自己实现一个promise)更详细的注释和其它接口暂未完成,下次咱们继续。

// let myPromise;
// 确定promise的三种状态
let sum = 0;
const PENDING = 'pending', 
    FULFILLED = 'fulfilled',
    REJECTED = 'rejected';

// 首先promise可以通过new关键字执行, 这里我们用class申明这个自定义方法
class MyPromise {
    RF_CB_LIST = [];
    RR_CB_LIST = [];
    _status = PENDING;
    /* 
        使用的时候这里通常会接收一个异步的Function来发送Ajax请求
    */
    constructor (fn) {
        /* 
            这里我们先初始化Promise的值
            设置init接口会暴露在实例对象以外 为了防止初始化被重复调用 也是因为init初始化不应该被重复调用更改状态吧方法放入私有域中初始化            
            初始化获取Promise的状态 成功的值 失败的值
        */
        this.status = PENDING;
        this._status = PENDING;
        this.value = null;
        this.reason = null;
        /* 
            这里我们就要对fn函数进行调用
            因为class中this指向问题
            为了防止传入的resolve 和reject的this指向问题造成status和value以及reason出现问题这里我们对this进行处理
        */
       if (this.isFunction(fn)) {
           try {
               fn(this.resolve.bind(this), this.reject.bind(this));
           } catch (error) {
               this.reject(error);
           }
       }
    }
    // 初始化promise
/*     init() {
        // 初始化获取Promise的值
        this.status = PENDING;
        this.value = null;
        this.reason = null;
    } */
    /*
    * promise有两个状态重置器 resolve和reject 
    */
    resolve (value) {
        // 状态判断 只有在初始状态时才能执行
        if (this.status = PENDING) {
            this.value = value;
            this.status = FULFILLED;
        }
    }
    reject (reason) {
        // 状态判断 只有在初始状态时才能执行
        if (this.status = PENDING) {
            this.reason = reason;
            this.status = REJECTED;
        }
    }
    /* 
        promise有两个回调方法 .then .catch 
        then接收两个参数 成功的回调和失败的回调切回调需要是函数在重置状态后调用
        then和catch会返回一个新的promise
    */
    then (onFulfilled, onRejected) {
        // 判断当前传入的值是否符合预期(函数类型) 否则将其重置为默认函数
        const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => {
            return value
        }
        const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => {
            throw reason;
        };
        // const realOnFulfilled = isFunction(onFulfilled) ? onFulfilled : returnVal;
        // const realOnRejected = isFunction(onRejected) ? onRejected : returnErr;
        // console.log(onFulfilled, onRejected)
        const promise = new MyPromise((resolve, reject) => {
            /* 
                queueMicrotask可以开启一个微任务
                realOnFulfilled或realOnRejected应该返回一个promise
                所以x应该是一个新的promise实例
                
                promise当前then将要返回的promise对象
                x是当前realOnFulfilled或realOnRejected函数应该返回的promise实例
                resolve是promise成功的状态重置器
                reject是promise失败的状态重置器

                resolvePromise(promise, x, resolve, reject)

            */
            const fulfilledQueueMicrotask = () => {
                queueMicrotask(() => {
                    try {
                        const x = realOnFulfilled(this.value);
                        this.realOnFulfilled(promise, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                })
            }
            const rejectedQueueMicrotask = () => {
                queueMicrotask(() => {
                    try {
                        const x = realOnRejected(this.reason);
                        this.resolvePromise(promise, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                })
            }
            switch (this.status){
                case FULFILLED:
                    fulfilledQueueMicrotask()
                    break;
                case REJECTED:
                    rejectedQueueMicrotask()
                    break;
                case PENDING:
                    /* 
                        因为js是同步执行的代码 如果是一个异步的resolve或者reject
                        那么在执行这段代码的时候可能状态还没变更 这时我们需要保存传入的回调
                        在状态变更的时候执行 引入get set
                    */
                   // 用数组是因为会有xxx.then多个这种调用方法 这时的then就需要放在数组里才方便遍历调用

                    this.RF_CB_LIST.push(fulfilledQueueMicrotask)
                    this.RR_CB_LIST.push(rejectedQueueMicrotask )
            }
        })
        return promise;
    }
    catch (onRejected) {
        return this.then(null, onRejected);
    }
    get status () {
        return this._status;
    }
    set status (val) {
        this._status = val;
        switch (val) {
            case FULFILLED:
                this.RF_CB_LIST.forEach((callback, index) => {
                    callback(this.value)
                })
                break;
            case REJECTED:
                this.RR_CB_LIST.forEach((callback, index) => {
                    callback(this.reason)
                })
                break;
        }
        return val;
    }
    isFunction (fn) {
        return Object.prototype.toString.call(fn) === '[object Function]';
    }
    isObject (obj) {
        return Object.prototype.toString.call(obj) === '[object Object]';
    }
    resolvePromise (promise, x, resolve, reject) {
        if (promise === x) {
            return reject(new TypeError('报错: 可能存在重复调用死循环'))
        }
        // 如果X传入的是自定义Promise方法
        if (x instanceof MyPromise) {
            /* 
                执行x的then方法, 如果执行时有个返回值res, 解析返回值res 
            */
            queueMicrotask(() => {
                x.then(
                    (res) => {
                        this.resolvePromise(promise, res, resolve, reject)
                    }, reject
                )
            })
        } else if (this.isObject(x) || this.isFunction(x)) {
                // 如果 x 为对象或者函数
                if (x === null) {
                    // null也会被判断为对象
                    return resolve(x);
                }
    
                let then = null;
    
                try {
                    // 把 x.then 赋值给 then 
                    then = x.then;
                } catch (error) {
                    // 如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise
                    return reject(error);
                }
    
                // 如果 then 是函数
                if (this.isFunction(then)) {
                    let called = false;
                    // 将 x 作为函数的作用域 this 调用
                    // 传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,第二个参数叫做 rejectPromise
                    try {
                        then.call(
                            x,
                            // 如果 resolvePromise 以值 y 为参数被调用,则运行 resolvePromise
                            (y) => {
                                // 需要有一个变量called来保证只调用一次.
                                if (called) return;
                                called = true;
                                this.resolvePromise(promise, y, resolve, reject);
                            },
                            // 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise
                            (r) => {
                                if (called) return;
                                called = true;
                                reject(r);
                            });
                    } catch (error) {
                        // 如果调用 then 方法抛出了异常 e:
                        if (called) return;
    
                        // 否则以 e 为据因拒绝 promise
                        reject(error);
                    }
                } else {
                    // 如果 then 不是函数,以 x 为参数执行 promise
                    resolve(x);
                }
        } else {
            resolve(x)
        }
    }
}

const test = new MyPromise((resolve, reject) => {
    // setTimeout(() => {
        reject(111);
    // }, 1000);
}).then(res => {console.log(res);}).catch(rej => {
    console.log('catch----------catch', rej)
}).then(res => {console.log(res);}).catch(rej => {
    console.log('catch----------catch2', rej)
}).catch(rej => {
    console.log('catch----------catch2', rej)
}).catch(rej => {
    console.log('catch----------catch2', rej)
})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值