Skip to content
/ lamb Public

A promise library in ES6 for learning Promise/A+ Specification.

License

Notifications You must be signed in to change notification settings

dzyhenry/lamb

Folders and files

NameName
Last commit message
Last commit date

Latest commit

fedab3d · Jul 19, 2017

History

19 Commits
May 3, 2017
Jan 5, 2017
Jan 5, 2017
Jan 5, 2017
Jan 6, 2017
Dec 20, 2016
May 3, 2017
Jul 19, 2017
Jan 5, 2017
May 3, 2017

Repository files navigation

Promises/A+ logo

Lamb npm

A promise library in ES6 for learning Promise/A+ Specification.

Run test

npm install & npm run test

Implementation Details

在实现过程中,参考Promise/A+规范,我们把Promise抽象成以下模块。

then

then方法是规范中定义的方法,同时也应该是Promise最重要的标识,主要特点如下:

  • then方法接受两个可选参数: onFulfilled, onRejected
  • then方法必须返回一个promise
  then(onFulfilled, onRejected) {
    const queuedPromise = new Lamb();
    if (Utils.isFunction(onFulfilled)) {
      queuedPromise.handlers.onFulfilled = onFulfilled;
    }
    if (Utils.isFunction(onRejected)) {
      queuedPromise.handlers.onRejected = onRejected;
    }
    this.queue.push(queuedPromise);
    this.process();
    return queuedPromise;
  }

transition

transition方法检查promise当前state的合法性并更新其statevalue,并将接下来的处理交给process方法。

  transition(state, value) {
    if (this.state === state || this.state !== VALIDATE_STATE.PENDING || !Utils.isValidateState(state) ||
      arguments.length !== 2) {
      return;
    }
    this.state = state;
    this.value = value;
    this.process();
  }

process

  • 我们知道当一个promise(姑且将这个promise叫做base promise)的then方法执行时,then方法创建的新的promise(queuedPromise)会被push到base promise的pending queue中。
  • transiton方法执行后,base promisestatevalue更新
  • then方法执行后,base promisepending queue push 新的queuedPromise
  • process方法会在then方法和transition方法中被调用,处理后续流程。
  process() {
    if (this.state === VALIDATE_STATE.PENDING) {
      return;
    }
    const that = this;
    // 2.2.4 onFulfilled or onRejected must not be called until the execution context stack contains only platform code.
    Utils.runAsync(() => {
      while (that.queue && that.queue.length) {
        const queuedPromise = that.queue.shift();
        let handler = null;
        let value = null;
        if (that.state === VALIDATE_STATE.FULFILLED) {
          handler = queuedPromise.handlers.onFulfilled || Utils.defaultFulfillCallback;
        } else if (that.state === VALIDATE_STATE.REJECTED) {
          handler = queuedPromise.handlers.onRejected || Utils.defaultRejectCallback;
        }

        try {
          value = handler(that.value);
        } catch (e) {
          queuedPromise.transition(VALIDATE_STATE.REJECTED, e);
          continue;
        }
        resolve(queuedPromise, value);
      }
    });
  }

Process runs the Promise Resolution procedure on all internally stored promises (i.e. those that were attached to the base promise through the then function) and enforces the following Promise/A+

resolve

resolve可能是promise最核心的模块,它处理promise的“解决”(resolve)过程。依照Promise/A+规范的定义,resolve方法的形式为: [[Resolve]](promise, x)

const resolve = (x) => {
  if (x === this) {
    // 当需要resolve的x是当前promise的时候,直接reject,并抛出TypeError异常
    promise.transition(VALIDATE_STATE.REJECTED, new TypeError('The promise and its value refer to the same object.'));
  } else if (Utils.isPromise(x)) {
    // 当x的类型是promise且非当前promise时,根据x的state进行相应处理
    if (x.state === VALIDATE_STATE.PENDING) {
      // 若x的state为pending时,当前promise的resolve被延迟
      x.then(value => resolve(this, value), reason => this.transition(VALIDATE_STATE.REJECTED, reason));
    } else {
      // 若x的state为fulfilled或者rejected,则使用x的state和value应用于当前promise
      this.transition(x.state, x.value);
    }
  } else if (Utils.isObject(x) || Utils.isFunction(x)) {
    // 若x的类型为Ojbect或者function时(thenable),检查该对象上是否有then方法
    let then = null;
    let isCalled = false;
    try {
      then = x.then;
      if (Utils.isFunction(then)) {
        then.call(x, (value) => {
          if (!isCalled) {
            resolve(this, value);
            isCalled = true;
          }
        }, (reason) => {
          if (!isCalled) {
            this.reject(reason);
            isCalled = true;
          }
        });
      } else {
        this.fulfill(x);
        isCalled = true;
      }
    } catch (e) {
      if (!isCalled) {
        this.reject(e);
        isCalled = true;
      }
    }
  } else {
    this.fulfill(x);
  }
};

Utils && state

  • 根据Promis/A+规范Promise有3个状态: PENDING, FULFILLED(settled), REJECTED(settled)
  • 处于FULFILLEDREJECTED状态的promise,其状态不能再进行转移。
  const VALIDATE_STATE = {
    PENDING: 0,
    FULFILLED: 1,
    REJECTED: 2,
  };

  const Utils = {
    // 异步执行帮助函数
    runAsync: (fn) => {
      setTimeout(fn, 0);
    },
    // 判断一个值是否是promise类型
    isPromise: p => p && p instanceof Lamb,
    // 判断一个值是否是对象类型
    isObject: value => value && typeof value === 'object',
    // 判断一个值是否是函数类型
    isFunction: value => value && typeof value === 'function',
    // 默认的`fulfill`函数
    defaultFulfillCallback: value => value,
    // 默认的`reject`函数
    defaultRejectCallback: (reason) => { throw reason; },
    // 判断一个状态是否是合法的promise状态
    isValidateState: state => (state === VALIDATE_STATE.PENDING) || (state === VALIDATE_STATE.FULFILLED) ||
      (state || VALIDATE_STATE.REJECTED),
  };

fulfill && reject

fulfillreject分别会将当前promise的状态转移到settled(fulfilled or rejected)状态,并交由transition方法进行后续处理

  reject(reason) {
    this.transition(VALIDATE_STATE.REJECTED, reason);
  }

  fulfill(value) {
    this.transition(VALIDATE_STATE.FULFILLED, value);
  }

References

About

A promise library in ES6 for learning Promise/A+ Specification.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published