implement Promise use typescript

131 阅读2分钟

试着实现Promise

首先真实的Promise结构如下:

const executor = function (resolve, reject) {
  resolve(1);
};
p1 = new Promise(executor);
p1.then((result) => {
  console.log(result);
});

可以看到 Promise构造函数接受一个函数executor作为参数,该函数又有两个参数resolvereject,这两个参数都是函数,当执行到resolve时,会触发then方法,所以该函数需要实现下面几点:

  1. 构造函数接受一个函数executor,该函数有两个参数,resolve和reject
  2. 执行该函数executor(resolve,reject)
  3. 在执行到resolve时,完成状态转化,调用then函数,如果出错则调用catch方法

v1版本

type Executor = (resolve: Resolve, reject: Reject) => void;

type Fn = (params?: any) => void;

type Resolve = (value?: any) => void;

type Reject = (value?: any) => void;

enum State {
  Pending = "Pending",
  OnFullFilled = "OnFullFilled",
  OnRejected = "OnRejected",
}

export class PromiseImpl {
  private state: State = State.Pending;
  private data = null;
  private onFullFilledArr: Fn[] = [];
  private onRejectArr: Fn[] = [];
  constructor(executor: Executor) {
    const resolve = (value: any) => {
      this.data = value;
      this.state = State.OnFullFilled;
      this.onFullFilledArr.forEach((fn) => fn(this.data));
    };

    const reject = (value: any) => {
      this.data = value;
      this.state = State.OnRejected;
      this.onRejectArr.forEach((fn) => fn(this.data));
    };

    executor(resolve, reject);
  }

  then(onFullFilledFn: Fn, onRejectedFn?: Fn) {
    if (this.state === State.Pending) {
      this.onFullFilledArr.push(onFullFilledFn);
      onRejectedFn && this.onRejectArr.push(onRejectedFn);
    }
    if (this.state === State.OnFullFilled) {
      onFullFilledFn(this.data);
    }

    if (this.state === State.OnRejected) {
      onRejectedFn && onRejectedFn(this.data);
    }
  }
}

未实现链式调用,链式调用依然返回了一个Promise

const p = new PromiseImpl((resolve, reject) => {
    setTimeout(() => resolve('resolved first one'), 1000);
});
p.then((res) => {
    console.log(res);
    return res + ' do some calculation';
}).then(res => {
    console.log(res);
});

如何处理链式调用?

首先得返回一个Promise,然后执行onFullFilled,并将返回值放入resolve中

注意,这里的onFullFilledArr 是什么?

这里的onFullFilled应该是一个函数,包裹的是resolve(onFullFilled())

V2

export class PromiseImpl {
  private state: State = State.Pending;
  private data = null;
  private errDate = null;
  private onFullFilledArr: Fn[] = [];
  private onRejectArr: Fn[] = [];
  constructor(executor: Executor) {
    const resolve = (value: any) => {
      this.data = value;
      this.state = State.OnFullFilled;
      this.onFullFilledArr.forEach((fn) => fn(this.data));
    };

    const reject = (value: any) => {
      this.data = value;
      this.state = State.OnRejected;
      this.onRejectArr.forEach((fn) => fn(this.data));
    };

    executor(resolve, reject);
  }

  then(onFullFilledFn: Fn, onRejectedFn?: Fn) {
    return new PromiseImpl((resolve, reject) => {
      if (this.state === State.Pending) {
        this.onFullFilledArr.push(() => {
          try {
            const result = onFullFilledFn(this.data);
            resolve(result);
          } catch (e) {
            this.errDate = e;
            reject(e);
          }
        });
        onRejectedFn &&
          this.onRejectArr.push(() => {
            try {
              const result = onRejectedFn(this.data);
              reject(result);
            } catch (e) {
              reject(e);
            }
          });
      }
      if (this.state === State.OnFullFilled) {
        const result = onFullFilledFn(this.data);
        resolve(result);
      }

      if (this.state === State.OnRejected) {
        onRejectedFn && onRejectedFn(this.data);
      }
    });
  }
}

是否还有问题?

思考then 里面也可以返回Promise

const p1 = new Promise((resolve, reject) => {
    setTimeout(() => resolve('resolved first one'), 1000);
})

p1.then((res) => {
    console.log(res);
    return new Promise(resolve => {
        setTimeout(() => resolve('resolved second one'), 1000);
    });
}).then(res => {
    console.log(res);
});

一共产生了三个Promise

  1. p1
  2. 链式调用里then产生了一个
  3. then的onFullFilled里面返回了一个Promise

判断如果onFullFilled如果是Promise类型,则调用第二个的then方法

Promise的解决顺序 1-->3--->2

export class PromiseImpl {
  private state: State = State.Pending;
  private data = null;
  private errDate = null;
  private onFullFilledArr: Fn[] = [];
  private onRejectArr: Fn[] = [];
  constructor(executor: Executor) {
    const resolve = (value: any) => {
      this.data = value;
      this.state = State.OnFullFilled;
      this.onFullFilledArr.forEach((fn) => fn(this.data));
    };

    const reject = (value: any) => {
      this.data = value;
      this.state = State.OnRejected;
      this.onRejectArr.forEach((fn) => fn(this.data));
    };

    executor(resolve, reject);
  }

  then(onFullFilledFn: Fn, onRejectedFn?: Fn) {
    return new PromiseImpl((resolve, reject) => {
      if (this.state === State.Pending) {
        this.onFullFilledArr.push(() => {
          try {
            const fulfilledFromLastPromise = onFullFilledFn(this.data);
            if (fulfilledFromLastPromise instanceof PromiseImpl) {
              // 这个函数onFullFilledArr里的
              fulfilledFromLastPromise.then(resolve, reject);
            } else {
              resolve(fulfilledFromLastPromise);
            }
          } catch (e) {
            this.errDate = e;
            reject(e);
          }
        });
        onRejectedFn &&
          this.onRejectArr.push(() => {
            try {
              const result = onRejectedFn(this.data);
              reject(result);
            } catch (e) {
              reject(e);
            }
          });
      }
      if (this.state === State.OnFullFilled) {
        const result = onFullFilledFn(this.data);
        resolve(result);
      }

      if (this.state === State.OnRejected) {
        onRejectedFn && onRejectedFn(this.data);
      }
    });
  }
}

注意这里 fulfilledFromLastPromise.then(resolve, reject);

这里是将 该函数push 进了onFullFilledArr,然后再resolve的时候调用