前端手写: promise

3 阅读1分钟
class Promise {
  constructor(executor) {
    // 三种状态
    this.status = 'pending';
    this.value = null;
    this.reason = null;
    // 存放then回调
    this.onResolveCb = [];
    this.onRejectCb = [];

    const resolve = (val) => {
      if (this.status !== 'pending') return;
      this.status = 'fulfilled';
      this.value = val;
      this.onResolveCb.forEach(fn => fn());
    };

    const reject = (err) => {
      if (this.status !== 'pending') return;
      this.status = 'rejected';
      this.reason = err;
      this.onRejectCb.forEach(fn => fn());
    };

    try {
      executor(resolve, reject);
    } catch (e) {
      reject(e);
    }
  }

  then(onResolve, onReject) {
    // 兼容不传回调
    onResolve = onResolve || (v => v);
    onReject = onReject || (e => { throw e; });

    return new Promise((resolve, reject) => {
      // 同步已成功
      if (this.status === 'fulfilled') {
        setTimeout(() => resolve(onResolve(this.value)));
      }
      // 同步已失败
      else if (this.status === 'rejected') {
        setTimeout(() => reject(onReject(this.reason)));
      }
      // 异步pending,先存回调
      else {
        this.onResolveCb.push(() => {
          setTimeout(() => resolve(onResolve(this.value)));
        });
        this.onRejectCb.push(() => {
          setTimeout(() => reject(onReject(this.reason)));
        });
      }
    });
  }

  // 顺带加个catch,面试加分
  catch(fn) {
    return this.then(null, fn);
  }
}