按照PromiseA+规范实现Promise, 及async,await

177 阅读5分钟

PromiseA+规范

术语

1Promise是定义一个有then方法的对象和函数
2、thenable是一个可以有then方法的对象或函数
3、value 是Promise成功时的值,resolve(value)  value 可以是 thenable,promise,undefined等基本类型或引用类型
4、reason是Promise失败时的值,reject(reason)
5、exception是throw异常时抛出的

规范

Promise状态及他们之间的流转关系

1、pending初始状态,可以被改变

1、在resolve和reject之前都是这个状态
2、通过resolve->fulfilled状态
3、通过reject->rejected的状态

2、fulfilled最终态

1、是promise被resolve后是这个状态
2、它必须有一个value值

3、rejected最终态

1、一个Promise被reject后是这个状态
2、它必须有一个reason值

then应该是promise对外提供的一个方法,用来访问最终结果

Promise.then(onFulfilled, onRejected)
onFulfilled必须是函数,如果不是函数,应该被忽略。
onRejected必须是函数,如果不是函数,应该被忽略。

onFulfilled特性

 1、在Promise变成fulfilled时,应该调用onFulfilled,参数是value
 2、在promise变成fulfilled之前,不应该被调用
 3、只能被调用一次

onRejected特性

1、在Promise变成rejected时,应该调用OnRejected,参数是reason
2、在Promise变成rejected之前,不应该被调用
3、只能被调用一次

OnFulfilled和OnRejected执行时应该是在微任务里面

 微任务:是宏任务完成之后再去执行(实现时如何生成微任务)

then方法可以被执行多次

 1、promise状态变成fulfilled之后,所有的回调都会按照注册的顺序执行,按照.then顺序执行
 2、promise状态变成rejected之后,所有的回调都会按照注册的顺序执行,按照.then顺序执行

返回值

then的返回值应该是一个Promise
const promise2 = Promise.then(onFulfilled,  onRejectd);
1、onFulfilled或OnRejected,执行结果为X,调用resolvePromise
2、onFulfilled或OnRejected,如果不返回结果,抛出异常,返回值也需要被reject。
3、如果onFulfiled不是一个函数,Promise2以Promise1的value触发fulfilled
4、如果onFulfiled不是一个函数,Promise2以Promise1的reason触发rejected

resolvePromise

 resolvePromise(promise2, x, resolve, reject)
 1、如果promise2和x相等,那么 reject TypeError
 2、如果x是一个promise
     如果x是pending状态,那么promise必须要在pending,直到x变成fulfilled or rejected.
     如果x被fulfilled,fulfill promise with the same value.
    如果x被rejected,reject promise with the same reason.
  3、如果x是一个object或者是一个function
    let then = x.then如果x.then这步出错,那么reject promise with the same reason.
    如果then是一个函数,then.call(x, resolvePromiseFn, rejectPromise)
    resolvePromiseFn的入参是y,执行resolvePromise(promise2, y, resolve, reject);
    rejectPromise的入参是r, reject promise with r.
    如果resolve Promise和rejectPromise都调用了,那么第一个调用优先,后面的调用忽略。
    如果调用then抛出异常e
    如果resolvePromise 或 rejectPromise 已经被调用,那么忽略则reject promise wiht the same reason..
    如果then不是一个function。fulfill promise with x.
     

按照规范实现Promise

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MPromise{
    FULFILLED_CALLBACK_LIST = [];
    REJECTED_CALLBACK_LIST = [];
    _status = PENDING;
    constructor(fn){
        this.status = PENDING;
        this.value = null;
        this.reason = null;
        try{
            fn(this.resolve.bind(this), this.reject.bind(this));
        }catch(e){
            this.reject(e)
        }
    }

    get status(){
        return this._status;
    }

    set status(newStatus){
        this._status = newStatus;
        switch(newStatus){
            case FULFILLED: {
                this.FULFILLED_CALLBACK_LIST.forEach(callback =>{
                    callback(this.value);
                });
                break;
            }
            case REJECTED: {
                this.REJECTED_CALLBACK_LIST.forEach(callback=>{
                    callback(this.reason);
                })
                break;
            }
        }

    }

    resolve(value){
        if(this.status === PENDING){
            this.status = FULFILLED;
            this.value = value;
        }
        
    }
    reject(reason){
        if(this.status === PENDING){
            this.status = REJECTED;
            this.reason = reason;
        }
    }
    then(onFulfilled, onRejected){
        var self = this;
        const fulfilledFn = this.isFunction(onFulfilled) ? onFulfilled : (value)=>{
            return value;
        }
        const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason) =>{
            throw reason;
        }

        var thenPromise = new MPromise((resolve, reject)=>{
            const fulFiledMicroQueueTask = cb =>{
                queueMicrotask(()=>{
                    try {
                        const x = fulfilledFn(this.value)
                        self.resolvePromise(thenPromise, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                        throw new Error(error);
                    }
                })
            }
            
            const rejectedMicroQueueTask = cb =>{
                queueMicrotask(()=>{
                    try {
                        const x = rejectedFn(this.value)
                        self.resolvePromise(thenPromise, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                        throw new Error(error);
                    }
                })
            }
            
            
            
            switch(this.status){
                case FULFILLED: {
                    fulFiledMicroQueueTask();
                }
                case REJECTED: {
                    rejectedMicroQueueTask();
                }
                case PENDING: {
              self.FULFILLED_CALLBACK_LIST.push(fulFiledMicroQueueTask);
                    self.REJECTED_CALLBACK_LIST.push(rejectedMicroQueueTask);
                    
                }
            }
        })


        

        return thenPromise;
    }
    
    resolvePromise(thenPromise, x, resolve, reject){
        if(x === thenPromise){
            throw new Error('不能返回自身')
        }

        if(x instanceof MPromise){
           queueMicroTask(()=>{
               x.then((y)=>{
                   this.resolvePromise(thenPromise, y, resolve, reject);
               }, reject);
           })
        } else if(typeof x === 'object' || this.isFunction(x) ) {
            if(x === null){
                return resolve(x);
            }
            
            let then = null;
            try{
                then = x.then;
            }catch(e){
                reject(e);
            }
            
            if(this.isFunction(then)){
                let called = false;
                try{
                    then.call(x,
                    (y)=>{
                        if(called){
                               return ; 
                        }
                        called = true;
                        this.resolvePromise(thenPromise, y,resolve, reject);
                    },
                    r=>{
                        if(called){
                           return ; 
                        }
                        called = true;
                        reject(r);
                    }
                }catch(e){
                    if(called){
                       return ; 
                    }
                    called = true;
                    reject(e);
                }
                
            
            }
            
        } else {
            resolve(x);
        }
    
    }
    
    
    isFunction(param){
        return typeof param === 'function';
    }

    catch(onRejected){
        return this.then(null, onRejected);
    }

    static resolve(value){
        if(value instanceof MPromise){
            return value;
        }

        return new MPromise((resolve)=>{
            resolve(value);
        })
    }

    static reject(reason){
        return new MPromise((resolve, reject) =>{
            reject(reason);
        })
    }

    static all(promiseList){
        return new MPromise((resolve, reject) => {
            const length = promiseList.length;
            for(let i = 0; i< length; i++){
                promiseList[i].then(function(data){
                    arr[index] = data;
                    if(i==length-1){
                        resolve(arr);
                    }
                }, reject)
            }
        })
    }

    static race(promiseList){
        return new MPromise((resolve, reject) => {
            for(var i = 0; i< promiseList.length; i++){
                promiseList[i].then(resolve, reject)
            }
        })
    }
}

const test = new MPromise((resolve, reject) =>{
    setTimeout(()=>{
        resolve(111);
    }, 1000);
}).then(console.log);
console.log(test)

setTimeout(()=>{
    console.log(test);
}, 2000)

genterator

迭代器 Iterator

迭代器Iterator 是 ES6 引入的一种新的遍历机制,同时也是一种特殊对象,它具有一些专门为迭代过程设计的专有接口。

每个迭代器对象都有一个next()方法,每次调用都返回一个当前结果对象。当前结果对象中有两个属性:

  1. value:当前属性的值

  2. done:用于判断是否遍历结束,当没有更多可返回的数据时,返回true

每调用一次next()方法,都会返回下一个可用的值,直到遍历结束。

生成器 Generator

生成器是一种返回迭代器的函数,通过function关键字后的星号(*)来表示,函数中会用到新的关键字yield。星号可以紧挨着function关键字,也可以在中间添加一个空格.

// yield 暂停标志
// next方法可以恢复执行。
function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}

var hw = helloWorldGenerator();
hw.next();
//{value: 'hello', done: false}
hw.next();
//{value: 'world', done: false}
hw.next();
//{value: 'ending', done: true}
hw.next();
//{value: undefined, done: true}

async,await

async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已。 根据语法规格,await命令只能出现在 async 函数内部,否则都会报错。

WX20220123-074745@2x.png

async function fn(args){}
// 等同于
function fn(args){
    return  spawn(function* (){
    
    });
}

function spawn(genF) {
  return new Promise(function(resolve, reject) {
    const gen = genF();
    function step(nextF) {
      let next;
      try {
        next = nextF();
      } catch(e) {
        return reject(e);
      }
      if(next.done) {
        return resolve(next.value);
      }
      Promise.resolve(next.value).then(function(v) {
        step(function() { return gen.next(v); });
      }, function(e) {
        step(function() { return gen.throw(e); });
      });
    }
    step(function() { return gen.next(undefined); });
  });
}