MPromise

109 阅读3分钟

Basic 😎

const p = new Promise((resolve, reject) => {
  resolve('哈哈');
  reject('不开心');
  throw('一个错误');
});
p.then((v) => console.log(v), (r) => console.log(r));
console.log(p);

image.png

  • 类有两个属性,PromiseState & PromiseResult
    • PromiseState有三种值:pendingfulfilledrejected
    • 执行resolve =》PromiseState由pending变为fulfilled
    • 执行reject =》PromiseState由pending变为rejected
    • PromiseResult为resolve或reject传入的值
class MPromise {
  constructor(executor) {
    // 类有两个属性
    this.MPromiseState = 'pending';
    this.MPromiseResult = undefined;
    try {
      // 构造函数的入参为一个`立即执行的函数`,这个立即执行的函数的入参,是`两个函数`
      // 立即执行函数的执行环境不一定,所以this要手动绑定一下
      // 立即执行函数的抛错,可以用catch接收一下,直接执行reject
      executor(this.resolve.bind(this), this.reject.bind(this));
    } catch (e) {
      this.reject(e);
    }
  }
  resolve(v) {
    // PromiseState改变之后,状态锁定🔒
    if(this.MPromiseState !== 'pending') return;
    this.MPromiseState = 'fulfilled';
    this.MPromiseResult = v;
  }
  reject(r) {
    // PromiseState改变之后,状态锁定🔒
    if(this.MPromiseState !== 'pending') return;
    this.MPromiseState = 'rejected';
    this.MPromiseResult = r;
  }
  // 实例的then方法,入参为两个函数:onResolve、onReject,由PromiseState的值来决定执行哪个回调,并将PromiseResult作为入参传入该回调函数
  then(onResolve, onReject) {
    if(this.MPromiseState === 'fulfilled') {
      if(typeof onResolve !== 'function') return this.MPromiseResult;
      onResolve(this.MPromiseResult);
    }
    if(this.MPromiseState === 'rejected') {
      if(typeof onReject !== 'function') throw this.MPromiseResult;
      onReject(this.MPromiseResult);
    }
  }
}

异步 😅

const p = new MPromise((resolve, reject) => {
  setTimeout(() => resolve('哈哈'), 1000);
});
p.then((v) => console.log(v), (r) => console.log(r));
console.log(p);

  • 立即执行函数中的异步:也就是MPromiseState为pending,所以在实例then方法中要在加个pending的判断
  • 这个判断里写什么呢...肯定是执行回调函数啊
    • 我们期望的流程:setTimeout=>resolve('哈哈')=>thenonResolve
    • 所以,回调函数要先暂存一下,然后在resolvereject中调用
class MPromise {
  constructor(executor) {
    this.MPromiseState = 'pending';
    this.MPromiseResult = undefined;
    // 用来存回调函数的
    this.callbacks = [];
    try {
      executor(this.resolve.bind(this), this.reject.bind(this));
    } catch (e) {
      this.reject(e);
    }
  }
  
  resolve(v) {
    if(this.MPromiseState !== 'pending') return;
    this.MPromiseState = 'fulfilled';
    this.MPromiseResult = v;
    // 在这里执行
    this.callbacks.forEach(callback => {
      callback.onResolve(v);
    });
  }

  reject(r) {
    if(this.MPromiseState !== 'pending') return;
    this.MPromiseState = 'rejected';
    this.MPromiseResult = r;
    // 在这里执行
    this.callbacks.forEach(callback => {
      callback.onReject(r);
    });
  }

  then(onResolve, onReject) {
    if(this.MPromiseState === 'fulfilled') {
      if(typeof onResolve !== 'function') return this.MPromiseResult;
      onResolve(this.MPromiseResult);
    }
    if(this.MPromiseState === 'rejected') {
      if(typeof onReject !== 'function') throw this.MPromiseResult;
      onReject(this.MPromiseResult);
    }
    // 回调函数暂存!
    if(this.MPromiseState === 'pending') {
      this.callbacks.push({onResolve, onReject});
    }
  }
}

then的链式调用 🥹

上面this.callbacks为什么是个数组呢!因为支持链式调用啊~

const p = new MPromise((resolve, reject) => {
  // setTimeout(() => resolve('哈哈'), 1000);
  resolve('哈哈')
});
p.then(v => v, r => r).
  then((v) => console.log(v, 'resolve'), (r) => console.log(r, 'reject'));
console.log(p);
  • 上面第一个then,返回的是个v,这要第二个then怎么执行啊;所以,实例方法then的返回,要用自己来包装一下
then(onResolve, onReject) {
  return new MPromise((resolve, reject) => {
    // ......
  });
}

先改一下同步的情况

  then(onResolve, onReject) {
    return new MPromise((resolve, reject) => {
      if(this.MPromiseState === 'fulfilled') {
        try {
          const res = onResolve(this.MPromiseResult);
          if(res instanceof MPromise) {
            // 如果返回值是promise对象,返回值为成功,新promise就是成功;返回值为失败,新promise就是失败
            res.then(resolve, reject);
          } else {
            // 如果返回值非promise对象,新promise对象就是成功,值为此返回值
            resolve(res);
          }
        } catch (e) {
          reject(e);
        }
      }
      if(this.MPromiseState === 'rejected') {
        try {
          const res = onReject(this.MPromiseResult);
          if(res instanceof MPromise) {
            // 如果返回值是promise对象,返回值为成功,新promise就是成功;返回值为失败,新promise就是失败
            res.then(resolve, reject);
          } else {
            // 如果返回值非promise对象,新promise对象就是成功,值为此返回值
            resolve(res);
          }
        } catch (e) {
          reject(e);
        }
      }
      // ... ... 
    });
  }
  • 合并同类项,提一个方法出来;
  • 异步的回调函数们也是通过这个方法来包装
thenCallback(cb) {
  try {
    const res = cb(this.MPromiseResult);
    if(res instanceof MPromise) {
      // 如果返回值是promise对象,返回值为成功,新promise就是成功;返回值为失败,新promise就是失败
      res.then(resolve, reject);
    } else {
      // 如果返回值非promise对象,新promise对象就是成功,值为此返回值
      resolve(res);
    }
  } catch (e) {
    reject(e);
  }
}

完整的then

  then(onResolve, onReject) {
    return new MPromise((resolve, reject) => {
      const thenCallback = cb => {
        try {
          const res = cb(this.MPromiseResult);
          if (res instanceof MPromise) {
            // 如果返回值是promise对象,返回值为成功,新promise就是成功;返回值为失败,新promise就是失败
            res.then(resolve, reject);
          } else {
            // 如果返回值非promise对象,新promise对象就是成功,值为此返回值
            resolve(res);
          }
        } catch (e) {
          reject(e);
        }
      }

      if (this.MPromiseState === 'fulfilled') {
        thenCallback(onResolve);
      }
      if (this.MPromiseState === 'rejected') {
        thenCallback(onReject);
      }
      if (this.MPromiseState === 'pending') {
        this.callbacks.push({
          onResolve: thenCallback.bind(this, onResolve),
          onReject: thenCallback.bind(this, onReject)
        });
      }
    });
  }

GO ON ... 😭

写不下去了

参考:手写Promise原理