【笔记】实现promise

吐槽君 分类:javascript

根据 Promise/A+ 规范实现 Promise

1.Promise 状态

  1. promise 有三种状态且必须是三种状态中的一种,等待态 pending,解决态 fulfilled 或拒绝态 rejected.
  2. 当处于 pending 状态 可以变成 fulfilled 或 rejected 中的一种.
  3. 当处于 fulfilled 状态 状态不允许改变 且有一个 value.
  4. 当处于 rejected 状态 状态不允许改变 且有一个 reason.

总结:状态只能从 pending 改变一次 且要给一个 value

2.then 方法

  1. then 接收两个可选参数 onFulfilled,onRejected 且如果不是函数就要忽略(其实就是如果不是函数就给个默认函数).
  2. onFulfilled/onRejected 必须在 promise 被解决/拒绝(reslove/reject)后执行且(reslove/reject)的值最为第一个参数.
  3. 确保 onFulfilled 和 onRejected 异步地执行,并且应该在 then 方法被调用的那一轮事件循环之后用新的执行栈执行(创建一个宏任务 setTimeout).
  4. 同一个 promise 上的 then 可能会被调用多次所以 onFulfilled/onRejected 要按照 then 的顺序执行(for 队列里都执行一遍).
  5. then 必须返回一个 promise.

总结:then 有两个参数且必须返回一个 promise,onFulfilled(onRejected)异步按顺序执行

3.Promise 解决程序 [[Resolve]](promise, x)

  1. 如果 promise 和 x 是同一个对象,抛出 TypeError 使 promise 变成拒绝状态.
  2. 如果 x 是 promise 且是 pending 那么 promise 保持等待直到解决或者拒绝,如果是 fulfilled/rejected 那么用相同的值/原因,解决/拒绝 promise.
  3. 如果 x 是对象或者函数,将 x.then 赋值到 then.
    1. 如果 x.then 出错抛出异常 e,那么用 e 作为原因拒绝 promise.
    2. 如果 then 是一个函数,用 x 作为 this 调用它.then 方法的两个参数为 resolvePromise,rejectPromise,如果 resolvePromise 用一个值 y 调用,运行[[Resolve]](promise, y),因为 y 有可能还是 promise(递归获取不是 promise 的情况),如果 rejectPromise 用一个原因 r 调用,用 r 拒绝 promise.
  4. resolvePromise,rejectPromise 两者只能调用一次,也就是说状态只能改变一次.
  5. 如果调用 then 抛出异常 e,如果状态已经改变过一次(resolvePromise,rejectPromise 被调用过)则忽略,否则用 e 作为 reason 拒绝 promise.
  6. 如果 then 不是一个函数或者对象,用 x 解决 promise。

总结:x 是 promise 对象还是函数还是普通值进行不同处理

4.promise 实现

//promise有三种状态,所以
const PENDING = 'PENDING';
const RESLOVE = 'RESLOVE';
const REJECTED = 'REJECTED';
const resolvePromise = (promise2,x,reslove,reject) =>{
    if(promise2===x){
        return reject(new TypeError('Chaining cycle detected for promise #<Promise> --'))//满足3.1
    }
    let lock; //定义一个锁限制状态只能变一次 满足3.4
    if((typeof x === 'object' && x !== null)||typeof x === 'function'){ //
        try{
            let then = x.then; //满足3.3  then有可能是getter上定义的属性 也许就定义了throw Err
            if(typeof then === 'function'){ //满足3.3.2
                then.call(x,y=>{  //满足3.2 如果x的状态是pending就一直不执行这俩函数
                    if(lock)return;
                    lock = true;
                    resolvePromise(promise2,y,reslove,reject);//递归解析 直到不是promise而是普通值
                },r=>{
                    if(lock)return;
                    lock = true;
                    reject(r)
                })
            }else{  //{a:1,then:1} 这种情况
                reslove(x)
            }
        }catch(e){
            if(lock)return;  //满足3.5
            lock = true
            reject(e) //满足3.3.1
        }
    }else{
        reslove(x); //如果是普通值直接用x解决promise 满足3.6
    }
}
class MyPromise{
    constructor(executor){
        this.status = PENDING;
        this.value = undefined;//成功的值
        this.reason = undefined;//失败的原因
        this.onResolvedCallbacks = [];//存放成功的队列
        this.onRejectedCallbacks = [];//存放失败的队列
        const reslove = (value) =>{
            if(this.status===PENDING){  //限制状态只能改变一次
                this.status = RESLOVE;  //改变状态
                this.value = value;     //值
                this.onResolvedCallbacks.forEach(fn=>fn()); //一个promise掉多个then按顺序执行 同时满足2.4
            }
        }
        const reject = (reason) =>{
            if(this.status===PENDING){ //状态只能改变一次
                this.status = REJECTED;
                this.reason = reason;  //原因
                this.onRejectedCallbacks.forEach(fn=>fn());
            }
        }
        try{
            executor(reslove,reject)
        }catch(e){
            reject(e)
        }
    }
    catch(errCallback){
        return this.then(null,errCallback)
    }
    then(onFulfilled,onRejected){
        onFulfilled = typeof onFulfilled === 'function'?onFulfilled:v=>v; //满足2.1
        onRejected = typeof onRejected === 'function'?onRejected:e=>{throw e};
        let promise2 = new MyPromise((reslove,reject)=>{
            if(this.status === RESLOVE){
                setTimeout(() => { //下面和这个定时器一样 因为不加定时器promise2获取不到 满足2.3
                    try{
                        let x = onFulfilled(this.value);
                        resolvePromise(promise2,x,reslove,reject);
                    }catch(e){
                        reject(e);
                    }
                },0)
            }
            if(this.status === REJECTED){
                setTimeout(() => {
                    try{
                        let x = onRejected(this.reason);
                        resolvePromise(promise2,x,reslove,reject);
                    }catch(e){
                        reject(e);
                    }
                },0)
            }
            if(this.status === PENDING){ //到这如果是pending状态,那么将函数存起来等状态改变后在执行 满足2.2
                this.onResolvedCallbacks.push(()=>{
                    setTimeout(() => {
                        try{
                            let x = onFulfilled(this.value);
                            resolvePromise(promise2,x,reslove,reject);
                        }catch(e){
                            reject(e);
                        }
                    },0)
                })
                this.onResolvedCallbacks.push(()=>{
                    setTimeout(() => {
                        try{
                            let x = onRejected(this.value);
                            resolvePromise(promise2,x,reslove,reject);
                        }catch(e){
                            reject(e);
                        }
                    },0)
                })
            }
        })
        return promise2 //then 必须返回一个promise 满足2.5
    }

}
 

回复

我来回复
  • 暂无回复内容