关注前端小讴,浏览更多原创技术文章

回顾:Promise源码渐进式解读(一)
回顾:Promise源码渐进式解读(二)
回顾:Promise源码渐进式解读(三)
回顾:Promise源码渐进式解读(四)

残缺代码+正文,可对照浏览

Promise源码解读系列的最初 1 篇,详解Promise构造函数的最初几个办法及.finally,封装isArray判断对象是否为数组:

/* isArray办法:判断对象是否为数组 */function isArray(x) {  return Boolean(x && typeof x.length !== 'undefined')}

Promise.all - 源码

/** Promise构造函数的all属性,指向函数 * 参数arr:数组 */Promise.all = function (arr) {  // 返回一个新期约  return new Promise(function (resolve, reject) {    if (!isArray(arr)) {      return reject(new TypeError('Promise.all accepts an array')) // 参数必须是数组    }    var args = Array.prototype.slice.call(arr) // Array原型的slice办法,利用call绑定给arr(防止有自定义的slice办法)    if (args.length === 0) return resolve([]) // 若数组长度为0,则立刻执行执行器函数并返回,参数为空数组    // ↑相当于:new Promise((resolve, reject) => resolve([]))    var remaining = args.length    /**     * res()办法     * 参数i:数组下标     * 参数val:数组项     */    function res(i, val) {      try {        // console.log(args[i], val) // args[i]和val最后是一样的        /* 如果该项为对象或函数对象,则对其then属性做非凡解决 */        if (val && (typeof val === 'object' || typeof val === 'function')) {          var then = val.then          // 如果then指向一个函数(val是Promise类型或thenable对象),则做解决          if (typeof then === 'function') {            /* 将该项的then办法体内的this指向该项自身,并执行then()               Promise.prototype.then本来承受2个参数onFulfilled和onRejected,将function(val){}和reject回调别离作为这两个办法传给.then()                -> 创立Handler实例(this指向then前的Promise实例,即该项自身)                -> 调用handle办法,依据_state进行下一步操作                  -> 如_state为1,则调用Promise._immediateFn                   -> 调用onFulfilled(即function(val)),参数为期约的_value值,即调用function(self._value)                  (若_state为0,则将Handler实例放入then()前Promise实例(该项自身)的_deferrends数组,同步执行暂停,整端代码执行终止,返回该项,即待定的期约)            */            then.call(              val,              function (val) {                res(i, val) // 将期约的_value值作为val,再次调用res办法              },              reject            )            return          }        }        /* 重写该项:若该项为解决的期约则被重写为其解决值/回绝理由,若为非期约则不变 */        args[i] = val        // console.log(args[i], val)        // console.log(args)        /* 若所有的Promise都执行结束(没有待定的),则执行执行器函数的resolve回调,参数为解决后的数组 */        if (--remaining === 0) {          resolve(args) // doResolve()外部的done管制着resolve/reject办法只执行一次        }      } catch (ex) {        /* 只有其中一项出现异常,则全副执行退出,进入catch异样解决 */        reject(ex) // doResolve()外部的done管制着resolve/reject办法只执行一次      }    }    /* 循环数组,针对每一项执行res()办法 */    for (var i = 0; i < args.length; i++) {      res(i, args[i])    }  })}
  • 参数必须是数组,若为空数组则等同于new Promise((resolve, reject) => resolve([]))
  • 循环参数数组,若数组项为解决的期约,则被重写为其解决值/回绝理由,若为非期约则不变
  • 若所有的Promise都执行结束(没有待定的),则执行执行器函数的resolve回调,参数为解决后的数组

    • 若有待定的期约,则会始终期待,直到执行结束
  • 只有其中一项出现异常,则全副执行退出,进入catch异样解决

Promise.all - 阶段测试

setTimeout(  console.log,  0,  Promise.all(), // 参数不是数组  /* Promise { _state: 2, _handled: false, _value: 'TypeError: Promise.all accepts an array', _deferreds: null } */  Promise.all([]), // 参数是空数组  /* Promise { _state: 1, _handled: false, _value: [], _deferreds: null } */  new Promise((resolve, reject) => resolve([])), // 等效于Promise.all([])  Promise.all([1, 2, 3]), // 参数是数组,数组的每项不是Promise对象  /* Promise { _state: 1, _handled: false, _value: [ 1, 2, 3 ], _deferreds: null } */  Promise.all([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]), // 参数是数组,数组的每项是解决的Promise对象  /* Promise { _state: 1, _handled: false, _value: [ 1, 2, 3 ], _deferreds: null } */  Promise.all([    Promise.resolve(true),    Promise.resolve(true),    Promise.resolve(true),  ]),  /* Promise { _state: 1, _handled: false, _value: [true, true, true], _deferreds: null } */  Promise.all([Promise.resolve(1), Promise.reject(2), Promise.resolve(3)]), // 参数是数组,数组中有回绝的Promise对象  /* Promise { _state: 2, _handled: false, _value: 2, _deferreds: null } */  Promise.all([Promise.resolve(1), new Promise(() => {}), Promise.resolve(3)]) // 参数是数组,数组中有待定的Promise对象  /* Promise { _state: 0, _handled: false, _value: undefined, _deferreds: null } */)

Promise.race - 源码

/** Promise构造函数的race属性,指向函数 * 参数arr:数组 */Promise.race = function (arr) {  // 返回一个新期约  return new Promise(function (resolve, reject) {    if (!isArray(arr)) {      return reject(new TypeError('Promise.race accepts an array')) // 参数必须是数组    }    /* 循环数组,针对每一项执行resolve()和.then()办法(若参数为空数组,则不执行,返回待定的期约) */    for (var i = 0, len = arr.length; i < len; i++) {      /**       * Promise.resolve()办法       * 参数arr[i]:数组项       */      Promise.resolve(arr[i]) // 返回新期约        /* Promise.prototype.then()办法           Promise.prototype.then本来承受2个参数onFulfilled和onRejected,将fn的resolve和reject回调别离作为这两个办法传给.then()           -> 创立Handler实例(this指向then前的Promise实例,即Promise.resolve()返回的新期约)           -> 调用handle办法,依据_state进行下一步操作              -> 如_state为1,则调用Promise._immediateFn              -> 调用onFulfilled,参数为期约的_value值,即调用function(self._value)        */        .then(resolve, reject) // doResolve()外部的done管制着resolve/reject办法只执行一次,因而只有最先落定(解决或回绝)的Promise执行了resolve/reject,前面的Promise都不执行    }  })  // 以Promise.race([3, 2, 1])为例,能够简化为new Promise((resolve,reject)=>{Promise.resolve(3).then(resolve, reject)})}
  • 参数必须是数组,若为空数组返回待定的期约
  • 循环参数数组,按顺序调用Promise.resolve,参数为数组项
  • 只有最先落定(解决或回绝)的Promise,依据其状态执行resolve/reject,前面的都不执行
  • 外围思路比对

    • Promise.allresolve数组所有项(如果该项是期约,则用其解决值/回绝理由替换)
    • Promise.race:一一Promise.resolve数组项(如果返回的期约已解决/回绝,则不再Promise.resolve前面的项)

Promise.race - 阶段测试

setTimeout(  console.log,  0,  Promise.race(), // 参数不是数组  /* Promise { _state: 2, _handled: false, _value: 'TypeError: Promise.race accepts an array', _deferreds: null } */  Promise.race([]), // 参数是空数组  /* Promise { _state: 0, _handled: false, _value: undefined, _deferreds: null } */  Promise.race([3, 2, 1]), // 参数是数组,数组的每项不是Promise对象  /* Promise { _state: 1, _handled: false, _value: 3, _deferreds: null } */  Promise.resolve(3), // 等效于Promise.race([3, 2, 1])  /* Promise { _state: 1, _handled: false, _value: 3, _deferreds: null } */  Promise.race([Promise.resolve(3), Promise.resolve(2), Promise.resolve(1)]), // 参数是数组,最先落定解决的Promise对象  /* Promise { _state: 1, _handled: false, _value: 3, _deferreds: null } */  Promise.race([Promise.reject(1), Promise.resolve(2), Promise.resolve(3)]), // 参数是数组,最先落定回绝的Promise对象  /* Promise { _state: 2, _handled: false, _value: 1, _deferreds: null }     Possible Unhandled Promise Rejection: 1 */  Promise.race([new Promise(() => {}), Promise.resolve(2), Promise.resolve(1)]) // 参数是数组,最先落定解决的Promise对象  /* Promise { _state: 1, _handled: false, _value: 2, _deferreds: null } */)

Promise.prototype.finally - 源码

/** Promise原型的finally属性,指向函数 * 参数callback:onFinally处理程序,在期约无论兑现还是回绝后,最终执行的回调 */Promise.prototype['finally'] = function (callback) {  // console.log(this, 'finally') // this指向finally()前返回的Promise实例  // console.log(this.constructor) // constructor指向Promise构造函数  // console.log(this.constructor === Promise) // true  var constructor = this.constructor  /* 调用Promise.prototype.then()办法,以下文setTimeout中的测试为例:     -> 创立Handler实例(this指向finally()前的Promise实例),创立新Promise实例     -> 调用handle(),_state为1,调用Promise._immediateFn,调用onFulfilled,调用后返回Promise实例(调用过程见onFulfilled外部)     -> 调用resolve(),传入Handler实例的promise和onFulfilled返回值(是一个Promise实例),将_state赋值为3,_value赋值为onFulfilled返回的Promise实例     -> 调用finale(),其_deferreds为[],赋为null后执行完结     -> 返回.then()外部创立的Promise实例:        Promise {           _state: 3,          _handled: false,          _value: Promise {            _deferreds: null,            _handled: false,            _state: 1,            _value: 2,          }          _deferreds: null        }  */  return this.then(    /* onFulfilled处理程序 */    function (value) {      /* 调用过程,以下文setTimeout中的测试为例:        -> 调用callback,打印finally3,返回3        -> 调用Promise.resolve(),创立解决的Promise实例,解决值为callback返回值3           此时then前的Promise实例为:Promise { _state: 1, _handled: false, _value: 3, _deferreds: null }        -> 调用.then()(外部this指向Promise.resolve()返回的期约,_state为1,_value为3),创立Handler实例(只有onFulfilled),创立新Promise实例        -> 调用handle(),外部state为1,将handled置为true,调用Promise._immediateFn,调用onFulfilled(即:function() {return value}),返回的value是finally前Promise实例的_value,即2        -> 调用resolve(),传入Handler实例的promise和onFulfilled返回值2,将_state赋值为1,_value赋值为2        -> 调用finale(),其_deferreds为[],赋为null后执行完结        -> 返回.then()外部创立的Promise实例(作为参数,传递给下层resolve()办法)           返回的Promise实例为:Promise { _state: 1, _handled: false, _value: 2, _deferreds: null }      */      // return constructor.resolve(callback())      return constructor.resolve(callback()).then(function () {        // console.log(value) // finally()前返回的Promise实例的解决值        return value      })    },    /* onRejected处理程序 */    function (reason) {      return constructor.resolve(callback()).then(function () {        // console.log(reason) // finally()前返回的Promise实例的回绝理由        return constructor.reject(reason) // 与onFulfilled不同的是,外部返回回绝的期约,回绝理由为finally()前Promise实例的回绝理由        /*           Promise._immediateFn最初一步均为调用resolve()办法,第二个参数若不是期约,则_state值会在resolve()中被赋为1          因而为了辨别与onFulfilled的区别,返回回绝的期约(而不是回绝理由),第二个参数是期约,_state值在resolve()中被赋为3          因而最终返回的期约,会多嵌套一层Promise(onFulfilled嵌套2层,onRejected嵌套3层),最内层为这个回绝的期约          Promise {             _state: 3,            _handled: false,            _value: Promise {              _deferreds: null,              _handled: false,              _state: 3,              _value: Promise { // 最内层为回绝的期约                _deferreds: null,                _handled: false,                _state: 2, // 此处的_state                _value: 2              }            }            _deferreds: null          }        */      })    }    /* 内层Promise实例赋给外层Promise实例的_value,逐层顺次赋值递推 */  )}

Promise.prototype.finally - 阶段测试

setTimeout(  console.log,  0,  Promise.resolve(2).finally(() => {    console.log('finally3') // 打印'finally3'    return 3  })  /* Promise为    Promise {      _state: 3,      _handled: false,      _value: Promise {        _state: 0,        _handled: false,        _value: undefined,        _deferreds: null      },      _deferreds: null    }  */  Promise.reject(2).finally(() => {    console.log('finally4') // 打印'finally4'    return 4  })  /* Promise为    Promise {      _state: 3,      _handled: false,      _value: Promise {        _state: 3,        _handled: false,        _value: Promise {          _state: 2,          _handled: false,          _value: 2,          _deferreds: null        },        _deferreds: null      },      _deferreds: null    }  */)

Promise.allSettled - 源码

/** Promise构造函数的allSettled属性,指向函数 * 参数arr:数组 */Promise.allSettled = function (arr) {  // console.log(this) // this指向Promise构造函数  var P = this  // 返回一个新期约  return new P(function (resolve, reject) {    // 参数必须是数组    if (!(arr && typeof arr.length !== 'undefined')) {      return reject(        new TypeError(          typeof arr +            ' ' +            arr +            ' is not iterable(cannot read property Symbol(Symbol.iterator))'        )      )    }    var args = Array.prototype.slice.call(arr) // Array原型的slice办法,利用call绑定给arr(防止有自定义的slice办法)    if (args.length === 0) return resolve([]) // 若数组长度为0,则立刻执行执行器函数并返回,参数为空数组    // ↑相当于:new Promise((resolve, reject) => resolve([]))    var remaining = args.length    /**     * res()办法     * 参数i:数组下标     * 参数val:数组项     */    function res(i, val) {      // console.log(args[i], val) // args[i]和val最后是一样的      /* 如果该项为对象或函数对象,则对其then属性做非凡解决 */      if (val && (typeof val === 'object' || typeof val === 'function')) {        var then = val.then        // 如果then指向一个函数(val是Promise类型或thenable对象),则做解决        if (typeof then === 'function') {          /* 将该项的then办法体内的this指向该项自身,并执行then()             Promise.prototype.then本来承受2个参数onFulfilled和onRejected,将function(val){}和function(e){}回调别离作为这两个办法传给.then()             -> 创立Handler实例(this指向then前的Promise实例,即该项自身)             -> 调用handle办法,依据_state进行下一步操作               -> 如_state为1,则调用Promise._immediateFn               -> 调用onFulfilled(即function(val)),参数为期约的_value值,即调用function(self._value)               (若_state为0,则将Handler实例放入then()前Promise实例(该项自身)的_deferrends数组,同步执行暂停,整端代码执行终止,返回该项,即待定的期约)          */          then.call(            val,            function (val) {              res(i, val) // 将期约的_value值作为val,再次调用res办法            },            function (e) {              args[i] = { status: 'rejected', reason: e } // 将该项重写为{status:'rejected',reason:谬误起因}              /* 若所有的项都执行结束,则执行执行器函数的resolve回调,参数为解决后的数组 */              if (--remaining === 0) {                resolve(args)              }            }          )          return        }      }      /* 重写该项:         若该项为解决的期约,则被重写为{status:'fulfilled',value:解决值}         若该项为回绝的期约,则被重写为{status:'rejected',reason:回绝理由}         若该项为非期约,则被重写为对象{status:'fulfilled',value:该项}      */      args[i] = { status: 'fulfilled', value: val }      // console.log(args[i], val)      // console.log(args)      /* 若所有的Promise都执行结束(没有待定的),则执行执行器函数的resolve回调,参数为解决后的数组 */      if (--remaining === 0) {        resolve(args) // doResolve()外部的done管制着resolve/reject办法只执行一次      }    }    /* 循环数组,针对每一项执行res()办法 */    for (var i = 0; i < args.length; i++) {      res(i, args[i])    }  })}
  • 参数必须是数组,若为空数组则等同于new Promise((resolve, reject) => resolve([]))
  • 循环参数数组,并重写:

    • 若该项为解决的期约,则被重写为{status:'fulfilled',value:解决值}
    • 若该项为回绝的期约,则被重写为{status:'rejected',reason:回绝理由}
    • 若该项为非期约,则被重写为对象{status:'fulfilled',value:该项}
  • 若所有的Promise都执行结束(没有待定的),则执行执行器函数的resolve回调,参数为解决后的数组

    • 若有待定的期约,则会始终期待,直到执行结束

Promise.allSettled - 阶段测试

setTimeout(  console.log,  0,  Promise.allSettled(), // 参数不是数组  /* Promise { _state: 2, _handled: false, _value: 'TypeError: undefined undefined is not iterable(cannot read property Symbol(Symbol.iterator))', _deferreds: null } */  Promise.allSettled([]), // 参数是空数组  /* Promise { _state: 1, _handled: false, _value: [], _deferreds: null } */  Promise.allSettled([3, 2, 1]), // 参数是数组,数组的每项都不是Promise对象  /*     Promise {      _state: 1,      _handled: false,      _value: [        { status: 'fulfilled', value: 3 },        { status: 'fulfilled', value: 2 },        { status: 'fulfilled', value: 1 }      ],      _deferreds: null    }  */  Promise.allSettled([    Promise.resolve(3),    Promise.resolve(2),    Promise.resolve(1),  ]), // 参数是数组,每项都是解决的Promise对象  /*     Promise {      _state: 1,      _handled: false,      _value: [        { status: 'fulfilled', value: 3 },        { status: 'fulfilled', value: 2 },        { status: 'fulfilled', value: 1 }      ],      _deferreds: null    }  */  Promise.allSettled([    Promise.resolve(1),    Promise.reject(2),    Promise.resolve(3),  ]), // 参数是数组,每项都是Promise对象,有回绝的期约  /*     Promise {      _state: 1,      _handled: false,      _value: [        { status: 'fulfilled', value: 1 },        { status: 'rejected', reason: 2 },        { status: 'fulfilled', value: 3 }      ],      _deferreds: null    }  */  Promise.allSettled([    Promise.resolve(2),    new Promise(() => {}),    Promise.resolve(1),  ]) // 参数是数组,每项都是Promise对象,有待定的期约  /* Promise { _state: 0, _handled: false, _value: undefined, _deferreds: [] } */)

实现后果总结

  • 实现Promise构造函数办法:Promise,allPromise.racePromise.allSettled
  • 实现Promise原型办法:Promise.prototype.finally

截至本节的代码 →