不太懂Promise所以试着手写Promise

85 阅读3分钟

文章一篇,试着写一下Promise。因为不太懂Promise所以试着手写Promise

虽然不太懂内部构造,但也是经常性的去使用,使用的都是一些常见的场景,个别的方法是用不上的,用到的时候再去百度。

开始

先看下原版的类型提示,按照提示写个大概。

\

Promise是个带泛型类,构造函数需要一个executor方法 方法默认会有2个参数,resolve,reject 2个方法,2个方法内各有一个any参数

//构造方法 参数 
executor:(resolve:(value:any)=>void,
          reject:(reason?:any)=>void)=>void

对比下平时写的结构,可以大概猜出是内部怎么个结构

function test() {  
    return new Promise((res, rej) => {    
        setTimeout(() => {      
            res(123);
        }, 10);  
    });
}
test().then((res) => {
    console.log(res);
  }).catch((err)=>{
  cosole.error(err)
});

那么开始

class MyPromise<T> {
  constructor(
    exectuor: (
      resolve: (value: any) => void,
      reject: (reason?: any) => void
    ) => void
  ) {
    exectuor(this.resolve, this.reject);
  }
  resolve(value: any): void {}
  reject(reason?: any): void {}
}

一个基础架子有了。开始添加内容。写resolve、reject2个方法

  resolve(value: any): void {    this._value = value;  }
  reject(reason?: any): void {    this._value = reason;  }

在promise的规范里,实际使用就是pending=>fulfilled|pending=>rejected,并且不可逆,所以还需要个status

resolve(value: any): void {
    if (this.status === "pending") {
      this._value = value;
      this.status = "fulfilled";
    }
  }
  reject(reason?: any): void {
    if (this.status === "pending") {
      this._value = reason;
      this.status = "rejected";
    }
  }

下面再开始写then和catch方法,一样的根据常用写法,then会传进来一个方法

test()
  .then((res) => {
    console.log(res);
  })
  .catch((err) => {
    cosole.error(err);
  });
then(fn: (value: any) => void) {
    if (this.status === "fulfilled") {
      fn(this._value);
    }
  }
  catch(fn: (value: any) => void) {
    if (this.status === "rejected") {
      fn(this._value);
    }
  }

感觉差不多了,试一下看看

class MyPromise {
  private _value;
  private status;
  constructor(
    exectuor: (
      resolve: (value: any) => void,
      reject: (reason?: any) => void
    ) => void
  ) {
    this._value = null;
    this.status = "pending";
    exectuor(this.resolve, this.reject);
  }
  resolve(value: any): void {
    if (this.status === "pending") {
      this._value = value;
      this.status = "fulfilled";
    }
  }
  reject(reason?: any): void {
    if (this.status === "pending") {
      this._value = reason;
      this.status = "rejected";
    }
  }
  then(fn: (value: any) => void) {
    if (this.status === "fulfilled") {
      fn(this._value);
    }
  }
  catch(fn: (value: any) => void) {
    if (this.status === "rejected") {
      fn(this._value);
    }
  }
}
function ass() {
  return new MyPromise((res, rej) => {
    setTimeout(() => {
      console.log(123);
      res(122);
    }, 10);
  });
}
ass().then((res) => {
  console.log(res);
});
//打印结果
123

结果发现只打印了123,then方法没有执行,测试下

then(fn: (value: any) => void) {
    console.log("then");
    if (this.status === "fulfilled") {
      fn(this._value);
    }
  }
//打印结果
then
123

看来then方法是执行了的,还是先执行的,是异步的问题。

不能让then 里的参数方法先执行,得拿到值之后再执行。

所以我们把then 里的方法放进resolve里,让异步结果先出来再来执行then里的方法

resolve(value: any): void {
    if (this.status === "pending") {
      this._value = value;
      this.status = "fulfilled";
      this.thenFuncs(this._value);
    }
  }

那么这时候,then 方法就成了收集方法的

resolve(value: any): void {
    if (this.status === "pending") {
      this._value = value;
      this.status = "fulfilled";
      this.thenFunc(this._value);
    }
  }
  reject(reason?: any): void {
    if (this.status === "pending") {
      this._value = reason;
      this.status = "rejected";
      this.catchFunc(this._value);
    }
  }
  then(fn: (value: any) => void) {
    if (this.status === "fulfilled") {
      fn(this._value);
    }
    if (this.status === "pending") {
      this.thenFunc = fn;
    }
  }
  catch(fn: (value: any) => void) {
    if (this.status === "rejected") {
      fn(this._value);
    }
    if (this.status === "pending") {
      this.catchFunc = fn;
    }
  }

我们再来跑一下,试试

123

嗯?方法还是没有执行?直接打印下看下

resolve(value: any): void {
    console.log(this.status);
    if (this.status === "pending") {
      this._value = value;
      this.status = "fulfilled";
      console.log(this.status);
      this.thenFunc(this._value);
    }
  }
//
123
undefined

status直接undefind,看来是resolve方法的this对象的问题。直接bind一下,看下完整的

class MyPromise {
  private _value;
  private status;
  private thenFunc;
  private catchFunc;
  constructor(
    exectuor: (
      resolve: (value: any) => void,
      reject: (reason?: any) => void
    ) => void
  ) {
    this._value = null;
    this.status = "pending";
    this.thenFunc = null;
    this.catchFunc = null;
    exectuor(this.resolve.bind(this), this.reject.bind(this));
  }
  resolve(value: any): void {
    console.log(this.status);
    if (this.status === "pending") {
      this._value = value;
      this.status = "fulfilled";
      this.thenFunc(this._value);
    }
  }
  reject(reason?: any): void {
    if (this.status === "pending") {
      this._value = reason;
      this.status = "rejected";
      this.catchFunc(this._value);
    }
  }
  then(fn: (value: any) => void) {
    if (this.status === "fulfilled") {
      fn(this._value);
    }
    if (this.status === "pending") {
      this.thenFunc = fn;
    }
  }
  catch(fn: (value: any) => void) {
    if (this.status === "rejected") {
      fn(this._value);
    }
    if (this.status === "pending") {
      this.catchFunc = fn;
    }
  }
}
function ass() {
  return new MyPromise((resolve, reject) => {
    setTimeout(() => {
      console.log(123);
      resolve(122);
    }, 10);
  });
}
ass().then((res) => {
  console.log(res);
});
//执行
123
pending
122

ok!初步完成

接下来还有then的调用,待更新