了解promise 其一:promise构造器

为了更好的理解promise 参考材料手写promise

手写promise一共两个核心东西

1:promise构造器

2:.then方法

class MyPromise {
    // 要做一个不让外面使用的 私有属性(内部属性)光靠_命名方式是不可靠的
    // 方案1 使用ES6的 symbol
    // 方案2 使用私有属性 在名字前面加#
    // _state = "pending";
    // _result = undefined;

    #state = "pending";
    #result = undefined;



    // 接收一个参数 立即执行
    constructor(executor) {


        //resolve、reject 主要就用就是改变状态设置结果
        const resolve = (data) => {
            // 因为promise的状态一旦确定下来之后,他就无法被更改了
            // 所以需要判断一下
            // 说明这个状态已经被更改过了 那就什么都不做
            if(this.#state !== 'pending') return ;
            this.#state = 'fulfilled';
            this.#result = data
        };
        const reject = (err) => {
            if(this.#state !== 'pending') return ;
            this.#state = 'rejected';
            this.#result = err
        };
        // this取决于函数如果调用的
        // executor(this.resolve, reject);
        // 如果非要写在原型上需要用 executor(this.resolve.bind(this), reject);  -- 但是道理是一样的,每一次调用构造器也会返回一个新的函数
        executor(resolve, reject);
    }

    // 虽然说每一次调用这个构造器就需要新建两个函数出来,但是也不能写在原型上
    // 会产生this指向问题
    // resolve(){ console.log(this) }
}

const p = new MyPromise((resolve, reject)=>{
    // 如果先返回resolve 后返回reject reject(2);就失效了
    // 因为promise的状态一旦确定下来之后,他就无法被更改了
    // resolve(1);
    // reject(2);
})

// p.#state = 'sdasdasd';  // 是它改变不了  -- 直接报错


因为上述有许多重复代码,所以改造一下

class MyPromise {
    // 要做一个不让外面使用的 私有属性(内部属性)光靠_命名方式是不可靠的
    // 方案1 使用ES6的 symbol
    // 方案2 使用私有属性 在名字前面加#
    // _state = "pending";
    // _result = undefined;

    #state = "pending";
    #result = undefined;

    // 接收一个参数 立即执行
    constructor(executor) {
        const resolve = (data) => {
            // 因为promise的状态一旦确定下来之后,他就无法被更改了
            // 所以需要判断一下
            // 说明这个状态已经被更改过了 那就什么都不做
            this.#changeState("fulfilled",data)
        };
        const reject = (err) => {
            this.#changeState("rejected",err)
        };

        executor(resolve, reject);
    }

    #changeState(state,result){
        if(this.#state !== 'pending') return ;
        this.#state = state;
        this.#result = result
    }
}

const p = new MyPromise((resolve, reject)=>{
    // 如果先返回resolve 后返回reject reject(2);就失效了
    // 因为promise的状态一旦确定下来之后,他就无法被更改了
    resolve(1);
    reject(2);
})



同时,发现这些状态都是写死的赋值,后面也可能大量的用到,那么最好不要写死

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'

class MyPromise {
    // 要做一个不让外面使用的 私有属性(内部属性)光靠_命名方式是不可靠的
    // 方案1 使用ES6的 symbol
    // 方案2 使用私有属性 在名字前面加#
    // _state = "pending";
    // _result = undefined;

    #state = PENDING;
    #result = undefined;

    // 接收一个参数 立即执行
    constructor(executor) {
        const resolve = (data) => {
            // 因为promise的状态一旦确定下来之后,他就无法被更改了
            // 所以需要判断一下
            // 说明这个状态已经被更改过了 那就什么都不做
            this.#changeState(FULFILLED,data)
        };
        const reject = (err) => {
            this.#changeState(REJECTED,err)
        };

        executor(resolve, reject);
    }

    #changeState(state,result){
        if(this.#state !== PENDING) return ;
        this.#state = state;
        this.#result = result
    }
}

const p = new MyPromise((resolve, reject)=>{
    // 如果先返回resolve 后返回reject reject(2);就失效了
    // 因为promise的状态一旦确定下来之后,他就无法被更改了
    resolve(1);
    reject(2);
})



还没完,当前是无法改变状态了,但是 

 如果执行期间promise抛出异常了(例:throw(123)) 需要用到try catch
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'

class MyPromise {
    // 要做一个不让外面使用的 私有属性(内部属性)光靠_命名方式是不可靠的
    // 方案1 使用ES6的 symbol
    // 方案2 使用私有属性 在名字前面加#
    // _state = "pending";
    // _result = undefined;

    #state = PENDING;
    #result = undefined;

    // 接收一个参数 立即执行
    constructor(executor) {
        const resolve = (data) => {
            // 因为promise的状态一旦确定下来之后,他就无法被更改了
            // 所以需要判断一下
            // 说明这个状态已经被更改过了 那就什么都不做
            this.#changeState(FULFILLED,data)
        };
        const reject = (err) => {
            this.#changeState(REJECTED,err)
        };

        // 只能捕获同步错误
        try{
            executor(resolve, reject);
        }catch (err) {
            reject(err);
        }

    }

    #changeState(state,result){
        if(this.#state !== PENDING) return ;
        this.#state = state;
        this.#result = result
        // 打印后只有完成没有拒绝 -- 只打印第一个
        console.log(this.#state,this.#result)
    }
}

const p = new MyPromise((resolve, reject)=>{
    // 如果先返回resolve 后返回reject reject(2);就失效了
    // 因为promise的状态一旦确定下来之后,他就无法被更改了
    resolve(1);
    reject(2);
})

// 如果执行期间promise抛出异常了,会更改当前状态
const p = new MyPromise((resolve, reject)=>{
    throw(123)
})





但是 try catch只能捕获同步错误,如果是异步错误,状态还是pending

const p = new MyPromise((resolve, reject)=>{
    setTimeout(()=>{
        throw(123)
    },100)
})

官方也没有解决办法,所以就不用管他了

总结思路:

1:创建一个类 MyPromise 

class MyPromise {
    constructor(){}
}

2: 后面就去调用这个类

const p = new MyPromise

3:在构造器中考虑第一个问题,需要接受一个参数,这个参数是一个任务,用于将来执行的

这个函数是一开始就运行的,执行这个函数的时候需要两个参数

 constructor(executor) {
      executor(resolve, reject);

    }

4:此时constructor中没有这两个参数,需要做这两个参数

const resolve = () => {} const reject= () => {}

5:考虑不能写在原型上的问题  --- 会出现this指向的问题

6:给const resolve 和 const reject设置参数 因为后期会传递参数,如果不传就是undefined

const resolve = (data) => {}; // 表示正确的结果
const reject = (err) => {};  // 表示错误的原因

7:进入这两函数里面了

resolve和reject的作用就是改变promise的状态 设置结果

打印出来:

promise {
 .......
 promiseState : "rejected",  // 状态
 promiseResult :1  // 结果
}

8:定义属性  并设置内部属性 #state(状态) #result(结果)

初始值

#state = PENDING;
#result = undefined;

9:定义完两个属性后,在方法内改变状态和结果

constructor(executor) {

        const resolve = (data) => {
           
            this.#state = 'fulfilled';
            this.#result = data
        };
        const reject = (err) => {
           
            this.#state = 'rejected';
            this.#result = err
        };
       
        executor(resolve, reject);
    }

10:处理在调用MyPromise时,resolve(1)和reject(2)同时调用时,promise的状态一会是fuifilled一会是reject,(两个都会执行)正常的promise中只会执行一行剩下的不会都执行(因为只要确定下来了后状态不会被更改了)

所以就需要判断一下当前状态不等于pending 说明状态已经被更改过了 那就什么也不做

constructor(executor) {

        const resolve = (data) => {
            
            if(this.#state !== 'pending') return ;
            this.#state = 'fulfilled';
            this.#result = data
        };
        const reject = (err) => {
            if(this.#state !== 'pending') return ;
            this.#state = 'rejected';
            this.#result = err
        };
        
        executor(resolve, reject);
    }

11:这时会发现有许多重复代码,遇到重复代码,需要提取代码

创建#changeState方法

    #changeState(state,result){

        this.#state = state;
        this.#result = result
        // 打印后只有完成没有拒绝 -- 只打印第一个
        console.log(this.#state,this.#result)
 
    }

12:对于状态判断最好不要用写死的字符串,需要提取一下

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'
class MyPromise {
     #state = PENDING;
    #result = undefined;


    // 接收一个参数 立即执行
    constructor(executor) {
        const resolve = (data) => {
          
            this.#changeState(FULFILLED,data)
        };
        const reject = (err) => {
            this.#changeState(REJECTED,err)
        };

    }


    #changeState(state,result){
        if(this.#state !== PENDING) return ;
        this.#state = state;
        this.#result = result
      
    }
}

13:当前虽然promise的状态不会完全切换了,但是当这个执行器的执行期间发生错误,会更改promise的状态的,这时就需要判断,如果在执行器中发现错误,那么就调用拒绝函数 reject

14:异步错误没招

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值