Promise的实现原理

大致思路

1、Promise的构造函数,只有一个函数参数resolver(resolve,reject),而函数参数resolver的两个参数都是函数参数,第一个参数resolve表示处理成功执行的函数,reject表示失败执行的函数

在构造函数中的属性有state(保存当前promise的状态);value(保存resolve或发生reject的错误原因);queue(Array,同一个promise可以多次调用then方法,这里是保存调用then方法之后生成的promise对象及其对应的resolve reject函数)

构造函数主要职责有:

a)初始化Promise的状态,this.state = PENDING

b)初始化resolve或reject的参数值,this.value = void 0

c)初始化then()注册的回调函数,this.queue = []

d)立即执行resolver(resolve,reject),即调用函数safelyResolveThen(self, then)-

立即执行resolver(resolve,reject)被封装在函数safelyResolveThen(self, then)----self为当前promise对象,resolver=then

这里就是执行函数resolver.

通过闭包对变量called的持有,使变量一直保存在内存中,达到resolve reject只执行一次,即同一个promise的状态由pending=>fulfilled或者pending => rejected只发生一次

在函数safelyResolveThen(self, then)里面调用了全局函数doResolve(self, value)和doReject(self, error)

doResolve(self, value)—doResolve 结合 safelyResolveThen 使用,不断地解包 promise 对象后,当值不是一个thenable对象时设置 promise 的状态和值。解包promise对象使用了方法getThen(value)。同时对queue遍历,通知queue中的每个promise的子promise,子promise 根据传入的值设置自己的状态和值

getThen(value)----如果value是一个thenable对象函数,那么就返回一个函数(在函数内,通过apply将value.then方法的作用域改成value,并执行then方法)

doReject(self, error) -----设置 promise的state为 REJECTED,value 为 error。同时遍历queue,对每个成员对象调用 callRejected,通知子 promise,子 promise 根据传入的错误设置自己的状态和值

2、Promise.prototype.then(onFulfilled, onRejected)----两个参数,成功时执行的回调函数onFulfilled,失败时执行的回调函数

onRejected。返回值是一个新生成的promise对象

根据当前promise的state状态来做相应的处理:

1)存在值穿透问题,即then方法没有参数或者参数为一个值

2)state不为PENDING,则执行unwrap(promise, resolver, this.value)。判断state为FULFILLED则resolver=onFulfilled,为REJECTED则resolver=onRejected。

3)否则promise的状态没有改变,即state=PENDIGN,将生成的promise对象和对应的onFulfilled, onRejected加入到当前promise的回调队列queue里面

unwrap(promise, resolver, this.value)----调用immediate.js将同步代码生成异步代码。同时执行回调函数,并验证处理的结果returnValue,如果为promise本身则抛出错误,否则调用doResolve(promise, returnValue)

Promise的静态方法

3、Promise.resolve(value)------返回一个promise对象;

a)value是一个promise对象则直接返回value;否则调用doResolve函数

b)value是一个thenable对象,将其转为promise对象,立即执行then方法,该promise的状态由这个thenable对象的then方法的具体设置而定;

c)value是一个原始值,或者是一个不具有then方法的对象,返回promise对象,状态为resolve

d)不带任何参数,直接返回一个promise对象

4、Promise.reject(reason)----返回一个promise对象;该实例的状态为rejected

直接返回doReject(promise, reason)处理后的结果

5、Promise.all(iterable)-------接受一个参数,返回一个promise。将多个promise封装成一个promise

返回promise的回调函数的参数值:

a)只有iterable中所有的promise对象的状态都变成fulfilled的时候,返回promise的状态才为fulfilled,且传递给返会promise对象的回调函数的参数为Array,元素由这些promise resolve之后的值组成

b)否则返回第一个被reject的实例的返回值,作为返回promise的回到函数的参数

6、Promise.race(iterable)-------接受一个参数,返回一个promise。将多个promise封装成一个promise

返回promise的回调函数的参数值:

a)返回第一个状态先改变的promise对象处理之后的值

'use strict';
 
var immediate = require('immediate');  //用immediate.js库将同步代码装成异步代码
 
function INTERNAL() {}
 
function isFunction(func) {
  return typeof func === 'function';
}
 
function isObject(obj) {  //Array   Object  Null  Set   Map 都为true
  return typeof obj === 'object';   
}
 
function isArray(arr) {
  return Object.prototype.toString.call(arr) === '[object Array]';
}
 
var PENDING = 0;    //控制promise对象的状态
var FULFILLED = 1;
var REJECTED = 2;
 
module.exports = Promise;  //输出模块
 
function Promise(resolver) {   //Promise构造函数
  if (!isFunction(resolver)) {
    throw new TypeError('resolver must be a function');
  }
  this.state = PENDING;  //初始化promise的状态为PENDIGN
  this.value = void 0;   //初始化resolve或reject的参数值
  this.queue = [];       //then方法可被同一个promise对象多次调用,用于注册新生成的promise对象
  if (resolver !== INTERNAL) {  
    safelyResolveThen(this, resolver);  //立即执行传进来的resolver函数
  }
}
 
function safelyResolveThen(self, then) {
  var called = false;  //called被用在闭包里面,使得它的值一直保存在内存中,用于promise的
  try {                 //called 控制 resolve 或 reject 只执行一次,多次调用没有任何作用
    then(function (value) {
      if (called) {
        return;
      }
      called = true;
      doResolve(self, value);
    }, function (error) {
      if (called) {
        return;
      }
      called = true;
      doReject(self, error);
    });
  } catch (error) {
    if (called) {
      return;
    }
    called = true;
    doReject(self, error);
  }
}
 
function doResolve(self, value) {  //doResolve 结合 safelyResolveThen 使用,不断地解包 
                                   // promise 对象后,设置 promise 的状态和值
  try {
    var then = getThen(value);
    if (then) {
      safelyResolveThen(self, then);  //value是一个thenable对象,则递归遍历直到是一个值
    } else {
      self.state = FULFILLED;
      self.value = value;
      self.queue.forEach(function (queueItem) {  //对queue遍历,执行当前promise对应的callFulfilled()
        queueItem.callFulfilled(value);  //callFulfilled通知子 promis, 子promise 根据传入的值设置自己的状态和值。
      });
    }
    return self;     //返回promise对象
  } catch (error) {
    return doReject(self, error);
  }
}
 
function doReject(self, error) {  // 设置 promise的state为 REJECTED,value 为 error
  self.state = REJECTED;
  self.value = error;
  self.queue.forEach(function (queueItem) {
    queueItem.callRejected(error);  // callRejected通知子 promise,子 promise 根据传入的错误设置自己的状态和值
  });
  return self; //返回当前promise对象
}
 
function getThen(obj) {  //传入的obj不为空,然后访问obj是否有then方法,有就返回obj.then(),否则为undefined
  var then = obj && obj.then;   // obj是一个thenable对象
  if ( obj && ( isObject(obj) || isFunction(obj) ) && isFunction(then) ) {
    return function appyThen() {
      then.apply(obj, arguments);
    };
  }
}
 
Promise.prototype.then = function (onFulfilled, onRejected) {
  if( !isFunction(onFulfilled) && this.state === FULFILLED ||
    !isFunction(onRejected) && this.state === REJECTED) {
    return this;   //实现了值穿透
  }
 
  // 生成新的promise对象
  var promise = new this.constructor(INTERNAL);
 
  //  promise 的状态改变了,则调用 unwrap
  if (this.state !== PENDING) {
    var resolver = this.state === FULFILLED ? onFulfilled : onRejected;
    unwrap(promise, resolver, this.value);
  } else {
    //promise对象状态没有改变,将生成的promise对象加入到当前promise的回调队列queue里面
    this.queue.push(new QueueItem(promise, onFulfilled, onRejected));
  }
  return promise;
};
 
Promise.prototype.catch = function (onRejected) {
  return this.then(null, onRejected);
};
 
function unwrap(promise, func, value) { //解包,参数分别为子promise  父promise的then的回调onFulfilled/onRejected
  immediate(function () {     // immediate()将同步代码变成异步代码          //父 promise 的值(正常值/错误)
    var returnValue;
    try {                 //捕获promise.then()   promise.catch()内部的异常
      returnValue = func(value);
    } catch (error) {
      return doReject(promise, error);
    }
 
    if (returnValue === promise) {  //返回的值不能是 promise 本身,否则会造成死循环
      doReject(promise, new TypeError('Cannot resolve promise with itself'));
    } else {
      doResolve(promise, returnValue);
    }
  });
}
 
 
// 类QueueItem具有的属性this.promise  this.callFulfilled   this.callRejected
function QueueItem(promise, onFulfilled, onRejected) {
  this.promise = promise;
 
  this.callFulfilled = function (value) {
    doResolve(this.promise, value);  //设置当前promise的状态和值
  };
 
  this.callRejected = function (error) {
    doReject(this.promise, error);
  };
 
  if (isFunction(onFulfilled)) {
    this.callFulfilled = function (value) {
      unwrap(this.promise, onFulfilled, value);
    };
  }
  if (isFunction(onRejected)) {
    this.callRejected = function (error) {
      unwrap(this.promise, onRejected, error);
    };
  }
}
 
Promise.resolve = resolve;
function resolve(value) {  //返回一个promise对象
  if (value instanceof this) {  //当 Promise.resolve 参数是一个 promise 时,直接返回该值
    return value;
  }
  return doResolve(new this(INTERNAL), value);  //否则调用doResolve函数
}
 
Promise.reject = reject;
function reject(reason) {    //返回一个promise对象。
  var promise = new this(INTERNAL);
  return doReject(promise, reason);  //调用doReject
}
 
 
Promise.all = all;
function all(iterable) {
  var self = this;
  if (!isArray(iterable)) {
    return this.reject(new TypeError('must be an array'));
  }
 
  var len = iterable.length;
  var called = false;
  if (!len) {
    return this.resolve([]);
  }
 
  var values = new Array(len);
  var resolved = 0;
  var i = -1;
  var promise = new this(INTERNAL);
 
  while (++i < len) {
    allResolver(iterable[i], i);
  }
  return promise;
  function allResolver(value, i) {
    self.resolve(value).then(resolveFromAll, function (error) {
      if (!called) {
        called = true;
        doReject(promise, error);
      }
    });
    function resolveFromAll(outValue) {
      values[i] = outValue;
      if (++resolved === len && !called) {
        called = true;
        doResolve(promise, values);
      }
    }
  }
}
 
Promise.race = race;
function race(iterable) {
  var self = this;
  if (!isArray(iterable)) {
    return this.reject(new TypeError('must be an array'));
  }
 
  var len = iterable.length;
  var called = false;
  if (!len) {
    return this.resolve([]);
  }
 
  var i = -1;
  var promise = new this(INTERNAL);
 
  while (++i < len) {
    resolver(iterable[i]);
  }
  return promise;
  function resolver(value) {
    self.resolve(value).then(function (response) {
      if (!called) {
        called = true;
        doResolve(promise, response);
      }
    }, function (error) {
      if (!called) {
        called = true;
        doReject(promise, error);
      }
    });
  }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值