Promise实现原理

实现原理

参考:
https://www.promisejs.org/implementing/
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

promise是一个状态机,代表了异步操作的结果,一个promise就是以下三个状态之一:

  • pending
  • fulfilled
  • rejected

当promise为成功或者拒绝之后,就不可再更改。

var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

function Promise() {
  var state = PENDING;
  var value = null;
  var handlers = [];
}

实现完成或者拒绝这两个关键状态的转变

  function fulfill(result) {
    state = FULFILLED;
    value = result;
  }
  function reject(error) {
    state = REJECTED;
    value = error;
  }
}

这两个转变仅仅针对于返回值为一个平凡值(plain value),应对返回值是更复杂的情况就提出了高级一点的resolve

  function resolve(result) {
    try {
      var then = getThen(result);
      if (then) {
        doResolve(then.bind(result), resolve, reject)
        return
      }
      fulfill(result);
    } catch (e) {
      reject(e);
    }
  }
}

resolve中使用到了两个辅助函数getThen()和doResolve(),如下:

/**
 * Check if a value is a Promise and, if it is,
 * return the `then` method of that promise.
 *
 * @param {Promise|Any} value
 * @return {Function|Null}
 */
function getThen(value) {
  var t = typeof value;
  if (value && (t === 'object' || t === 'function')) {
    var then = value.then;
    if (typeof then === 'function') {
      return then;
    }
  }
  return null;
}

/**
 * Take a potentially misbehaving resolver function and make sure
 * onFulfilled and onRejected are only called once.
 *
 * Makes no guarantees about asynchrony.
 *
 * @param {Function} fn A resolver function that may not be trusted
 * @param {Function} onFulfilled
 * @param {Function} onRejected
 */
function doResolve(fn, onFulfilled, onRejected) {
  var done = false;
  try {
    fn(function (value) {
      if (done) return
      done = true
      onFulfilled(value)
    }, function (reason) {
      if (done) return
      done = true
      onRejected(reason)
    })
  } catch (ex) {
    if (done) return
    done = true
    onRejected(ex)
  }
}

doResolve()接受了三个参数,第一个为函数(在resolve中就是指的result.then,onFulfilled即成功时的操作在前文中为resolve,onRejected即拒绝时的操作在前文中为rejected),先初始为未完成状态( done = false),fn接收两个函数为参数,第一个参数为成功时的操作,第二个参数为拒绝时的操作,因为onFulfilled为resolve,也就是在这里resolve会被调用到直到then不存在,去完成fulfill操作。
到此为止,状态机部分已经完成了,但我们的终极目标是去实现 .then,在此之前,.done 更简单,所以先去实现它。

promise.done(onFulfilled, onRejected)的为了实现

  • onFulfilled, onRejected只能调用其中一个
  • 只能调用一次
  • 在下一次回调之前不能被调用
  • 无论在我们调用.call之前或者之后promise已经被解决了,都会被调用
 function handle(handler) {
   if (state === PENDING) {
     handlers.push(handler);
   } else {
     if (state === FULFILLED &&
       typeof handler.onFulfilled === 'function') {
       handler.onFulfilled(value);
     }
     if (state === REJECTED &&
       typeof handler.onRejected === 'function') {
       handler.onRejected(value);
     }
   }
 }

 this.done = function (onFulfilled, onRejected) {
   // ensure we are always asynchronous
   setTimeout(function () {
     handle({
       onFulfilled: onFulfilled,
       onRejected: onRejected
     });
   }, 0);
 }

可看出在handle()部分实现了要么执行onFulfilled要么执行onRejected
.done实现之后,下面就是 .then 的实现,不同的是其中new了一个Promise

this.then = function (onFulfilled, onRejected) {
  var self = this;
  return new Promise(function (resolve, reject) {
    return self.done(function (result) {
      if (typeof onFulfilled === 'function') {
        try {
          return resolve(onFulfilled(result));
        } catch (ex) {
          return reject(ex);
        }
      } else {
        return resolve(result);
      }
    }, function (error) {
      if (typeof onRejected === 'function') {
        try {
          return resolve(onRejected(error));
        } catch (ex) {
          return reject(ex);
        }
      } else {
        return reject(error);
      }
    });
  });
}

/********************************************************/
this.then = function (onFulfilled, onRejected) {
  var self = this;
  return new Promise(function (resolve, reject) {
    return self.done(function (result) { /*resolve*/ }, 
    				 function (error) { /*reject*/ });
  });
}
  • 如果then中的回调函数返回一个值,那么then返回的Promise将会成为接受状态,并且将返回的值作为接受状态的回调函数的参数值
  • 如果then中的回调函数没有返回值,那么then返回的Promise将会成为接受状态,并且该接受状态的回调函数的参数值为 undefined
  • 如果then中的回调函数抛出一个错误,那么then返回的Promise将会成为拒绝状态,并且将抛出的错误作为拒绝状态的回调函数的参数值
  • 如果then中的回调函数返回一个已经是接受状态的Promise,那么then返回的Promise也会成为接受状态,并且将那个Promise的接受状态的回调函数的参数值作为该被返回的Promise的接受状态回调函数的参数值
  • 如果then中的回调函数返回一个已经是拒绝状态的Promise,那么then返回的Promise也会成为拒绝状态,并且将那个Promise的拒绝状态的回调函数的参数值作为该被返回的Promise的拒绝状态回调函数的参数值。
  • 如果then中的回调函数返回一个未定状态(pending)的Promise,那么then返回Promise的状态也是未定的,并且它的终态与那个Promise的终态相同;同时,它变为终态时调用的回调函数参数与那个Promise变为终态时的回调函数的参数是相同的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值