模拟实现Promise

 

Code:

var MiniPromise = (function MiniPromiseWrapper() {
  const PENDING = 'pending';
  const FULFILLED = 'fulfilled';
  const REJECTED = 'rejected';

  const _state = Symbol('state');
  const _result = Symbol('result');
  const _handler = Symbol('handler');
  const _changeState = Symbol('change_state_function');
  const _run = Symbol('run_function');
  const _handleThen = Symbol('handle_then');

  const microTaskQueue = (fn) => {
      if (typeof process === 'object' && typeof process.nextTick === 'function') {
          process.nextTick(fn);
      }
      else if (typeof MutationObserver === 'function') {
          const observer = new MutationObserver(fn);
          const textNode = document.createTextNode(' ');
          observer.observe(textNode, {
            characterData: true,
          });
          textNode.data = '';
      }
      else {
        setTimeout(fn, 0);
      }
  };

  const isPromiseLike = (val) => {
      if (val !== null && (typeof val === 'object' || typeof val === 'function')) {
          return typeof val.then === 'function';
      }
      return false;
  };

  class _MiniPromise {
      /**
       * 
       * @param {Function} executor 
       */
      constructor(executor) {
          this[_state] = PENDING;
          this[_result] = null;
          this[_handler] = []
          
          /**
           * 
           * @param {*} value 
           */
          const resolve = value => {
              this[_changeState](FULFILLED, value);
          };
          /**
           * 
           * @param {*} reason 
           */
          const reject = reason => {
              this[_changeState](REJECTED, reason);
          };

          // 如果在执行 executor 函数时报错(不能处理异步错误),则更改promise的状态(结果为err)
          try {
              executor(resolve, reject);
          }
          catch(err) {
              reject(err);
          }
      }

      [_changeState](state, result) {
          // 状态一旦改变,则不可逆
          if (this[_state] !== PENDING) {
              return;
          }
          this[_state] = state;
          this[_result] = result;
          this[_run]();
      }

      then(onFulfilled, onRejected) {
          return new _MiniPromise((resolve, reject) => {
              this[_handler].push({
                  onFulfilled,
                  onRejected,
                  resolve,
                  reject,
              });
              this[_run]();
          });
      }

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

      finally(onFinally) {
        const onResolve = (res) => {
          onFinally(res);
          return res;
        }
        const onReject = (err) => {
          onFinally(err);
          return err;
        };
        return this.then(onResolve, onReject);
      }

      [_handleThen](callback, resolve, reject) {
          microTaskQueue(() => {
              if (typeof callback !== 'function') {
                  const settled = this[_state] === FULFILLED ? resolve : reject;
                  settled(this[_result]);
                  return;
              }
              try {
                  const res = callback(this[_result]);
                  resolve(res);
              }
              catch(err) {
                  reject(err);
              }
          });
      }

      [_run]() {
          if (this[_state] === PENDING) {
              return;
          }
          while (this[_handler].length > 0) {
              const headItem = this[_handler].shift();
              const {
                  onFulfilled,
                  onRejected,
                  resolve,
                  reject,
              } = headItem;
              if (this[_state] === FULFILLED) {
                  this[_handleThen](onFulfilled, resolve, reject);
              }
              else if (this[_state] === REJECTED) {
                  this[_handleThen](onRejected, resolve, reject);
              }
          }
      }

      static resolve(val) {
          if (val instanceof Promise) {
              return val;
          }
          let _resolve;
          let _reject;
          const p = new MiniPromise((resolve, reject) => {
              _resolve = resolve;
              _reject = reject;
          });
          if (isPromiseLike(val)) {
              val.then(_resolve, _reject);
          }
          else {
              _resolve(val);
          }
          return p;
      }

      static reject(reason) {
          return new MiniPromise((_, reject) => {
              reject(reason);
          });
      }
  }

  return _MiniPromise;
})();

 

posted @ 2023-05-15 22:28  樊顺  阅读(17)  评论(0编辑  收藏  举报