promise模块源码

一、Promise-lib/core.js:Promise构造函数

(package.json中约定入口文件为index.js,通过index,js加载lib下的index.js文件,该index.js文件再加载core.js,作为模块输出Promise构造函数)

 

使用:

var fn=function(resolve,reject){
      setTimeout(function(){
            resolve();
      },3000);
}
new Promise(fn).then(function(){
      console.log("callback begin.")
})

 

 

功能需求:

延迟执行回调函数、链式调用、出错时执行reject状态回调。

特殊情况处理,包含:外部resolve函数的参数是Promise对象或Promise构造函数、绑定或不绑定当前Promise的then方法,通过bindPromise.then=Promise.then方式;

调用Promise.then时this关键字没有指向Promise实例,比如

var promise=Promise(fn)

function Callback(fn){

       var resolve=function(){};

       var reject=function(){};

       fn(resovle,reject);// onFulfilled,onRejected的返回值作为resolve、reject参数

};

promise.then.call(new Callback,onFulfilled,onRejected);

 

设计思路:

  • 延迟执行的思路仍在于延迟完成后添加回调函数。jquery-deferred模块巧用事件机制,在延迟完成后执行Callbacks对象的fire方法,使以Callbacks.add注册的回调函数队列同时得到执行。promise模块的解决思路是在延迟完成后添加resovle和reject函数,由resovle和reject函数获取回调函数所需的参数this._65,同时改变当前promise的状态this._81,在resovle和reject函数的尾部通过执行fianle函数,顺序执行handle函数、handleResolve函数,在handleResolve函数中,通过Promise.then方法注册的回调函数onFulfilled、onRejected最终得到执行。
  • 实现上述过程只差获取Promise.then方法注册的onFulfilled、onRejected回调函数,较为简单的设想是,为当前promise对象新增两个缓存onFulfilled、onRejected,在延迟完成后执行一系列函数时按条件执行这两个缓存函数既可以。然而Promise模块的设计思路是在模块内部构造Handler构造函数,在该构造函数创建的实例中,onFulfilled、onRejected回调函数分别通过this.onFulfilled和this.onRejected得到存储。至于Promise模块为何决定这样处理,参见第5条。
  • 链式回调的实现。jquery通过返回当前执行的jquery对象实现链式回调,jquery-deferred模块then、pipe方法通过返回一个最新创建的Deferred对象实现,Promise模块then方法的思路也在于以空函数noop新建一个Promise对象res(以空函数注册的Promise对象需要手动触发resolve、reject函数),并作为返回值res。相应地,返回值中也存在Promise对象所具有的方法。之所以Promise.then不返回当前处理的promise对象实现链式回调,一则需要管束回调函数队列,二则顺序执行的回调队列存在延迟函数时,无法实现该回调队列按理想顺序得到执行。如果返回新的Promise对象res,后续通过then注册的函数可以在回调函数onFulfilled、onRejected执行完成后得到调用,也就实现了链式注册的回调函数按理想顺序得到执行的需要。
  • 当Promise.then通过返回新的Promise对象res实现时,这一设计思路类同jquery-deferred模块的实现,然而jquery-deferred模块通过将新创建Deferred对象newDefer的启动函数resolveWith、rejectWith加入原始Deferred模块的Callbacks回调函数队列中,实现后续注册的回调函数得到陆续执行。Promise模块中,通过返回值res注册的回调函数仍需要手动启用resolve、reject函数以执行后续通过then方法注册的回调函数。简单的设想是将resolve、reject函数作为公共函数,以使返回值res的回调函数onFulfilled、onRejected通过this.resolve、this.reject得到执行。然而这样处理的歹处是向外暴露resolve、reject启动回调函数执行的接口,也就陷入jquery-deferred模块通过promise对象避免resolve、reject接口暴露的问题。因此启动函数resolve、reject必须是模块内部的私有方法。介于Promise对象的resolve和reject方法相同,因此可以用原始Promise对象的resolve、reject函数代替返回值res的resolve、reject函数。与此同时,resolve、reject函数构造要求是与Promise对象低耦合,Promise模块的实现是这两个函数的参数为self(当前处理的Promise对象)、newValue(外部函数fn中resolve、reject携带的参数值,或者回调函数onFulfilled、onRejected的返回值),以此使得这两个函数既能处理原始Promise对象,又能处理返回值res。相应地,后续处理函数fianle、handle、handleResolve也必须是私有函数。
  • 有了返回值Promise对象res,当前Promise对象需要存储的数据变为3个,一则是首次调用then方法加载的回调函数onFulfilled和onRejected,二则是通过返回值res.then方法加载的回调函数,后续加载的回调函数又可使用resolve(res,value)启动执行,因此缓存数据只需要保有onFulfilled、onRejected以及res即可。Promise模块通过构造Handler对象实现,this.promise指向返回值res,this.onFulfilled、this.onRejected分别指向首次调用then方法加载的回调函数onFulfilled、onRejected。该Handler对象在首次调用then方法时创建,通过handle函数赋值给promise._54,在没有闭包变量可作缓存容器的前提下,只好借用实例的属性保存回调函数onFulfilled、onRejected以及返回值res。设想Handler实例通过handle函数添加到promise._54属性中,并且触发的前提是当前Promise实例的状态是pending,也即promise._81=0,因而就有了一个疑问,为什么不把promise._54属性更新的函数独立出来。在延迟完成以后,执行回调函数的过程中,Promise模块通过finale函数使用处理含有回调函数onFulfilled、onRejected及返回值res的数组promise._54,在顺序交给handle函数、handleResolve函数作处理,最终执行onFulfilled、onRejected,使用resovle、reject函数启动执行res中注册的注册的回调函数。
  • Promise模块通过多次使用try-catch方式寻找并捕获错误,当捕获到错误时,即时启用reject函数执行相应的回调函数,当未曾捕获错误时,reject函数的执行有赖于外部函数fn使用过与之对应的reject函数。类比jquery-deferred模块,jquery-deferred模块除then方法处理错误,其他均不处理,按有无设置deferred.reject方法而执行。同时,try-catch方式也是不管执行时间到底有多久,只要一遇到错误就执行catch函数,就其延时处理的功能和Promise模块多少相似,而其实现尚待分析
  • 当外部函数fn中使用的resolve函数的参数是Promise对象或Promise构造函数时,分为两种情况,传参为另一个Promise对象调用当前Promise对象的then方法,如bindPromise.then=Promise.then类似形式,传参为其他Promise对象anoterPromise,且不绑定当前Promise对象的then方法。
  • 若传参为当bindPromise对象绑定当前Promse的then方法时,延迟函数fn已进入执行状态,无需重新执行外部函数fn,开启新一轮的延迟,因为后续注册的回调函数都通过与Promise对象无关的resolve、reject函数执行,以及陆续以noop空函数创建的Promise对象无法在使用者书写回调函数时获取,传参为bindPromise对象的意义也在于供函数内部调用作处理,通过bindPromise的resovle、reject函数给回调函数传递参数,而不是产生另一次当前Promise对象的延时。
  • 若传参为anotherPromise对象,通过doResovle执行该Promise对象的延时函数anotherFn,延时完成后执行then方法注册的回调函数。因为resovle、reject、finale、handle、handleResolved与Promise对象并无关联,所以当Promise模块发现外部resovle函数传参是anoterPromise对象时,可以通过及时终止内部resovle函数的执行,使then方法注册的回调函数也得不到调用;而当anotherFn执行完毕,又可以重新调用resovle函数触发then方法注册的回调得到执行。
  • 调用Promise.then时this关键字没有指向Promise实例,以功能需求中给出的示例为例,实现的是用onFulfilled、onRejected过滤传参,再交给外部回调函数resovle、reject作处理,没有反复链式调用的需求。因此then方法的返回值不是一个Promise对象,而是由构造函数this.constructor创建的实例,这一过程在safeThen函数中实现,与此同时创建该实例的过程里,以空函数noop创建新的Promise对象,并作为参数传入Handler构造函数中,以此实现设置两个回调函数的需求。延迟执行完成后,首先将执行onFulfilled、onRejected回调函数,再由这两个函数的返回值作为参数,执行外部回调函数resolve、reject,这两个函数在this.constructor实例中注册。问题是,这一设计是为了满足何种需求。

 

具体实现:

  • 构造函数Promise(fn),用于创建Promise对象实例,构造函数内部调用doResolve函数注册fn外部函数中使用的resolve、reject函数。在执行过程中传递resolve、reject函数,外部函数fn在Promise构造函数中也只是注册,具体的执行过程在doResolve函数中实现。作为外部函数的resolve、reject的功能需求是约定回调函数onFulfilled、onRejected的执行事件,其次是向onFulfilled、onRejected传递参数。
  • doResolve(fn,promise)函数,执行外部函数fn,注册外部函数resolve、reject,当延迟完成或失败时,外部函数通过Promise模块使用者手动调用执行,同时fn的执行状态done改写为true,调用内部resolve(promise,value)或reject(promise,value)触发回调函数执行。当外部fn函数执行失败,调用内部函数reject触发回调。
  • resolve(promise,newValue)成功resolve状态回调函数启动器,newValue通过外部函数获得或者由回调函数返回值构成。区分newValue是另一个Promise对象bindPromise拥有当前Promise对象的then方法,以及另一个Promise对象anotherPromise没有当前Promise对象的then方法,以及仅仅是普通的参数。
  1. 若为bindPromise情况,实现功能为用bindPromise向回调函数传参。执行过程中,promise._81状态改写为3,即adopted使用另一个Promise的回调,promise._65记录bindPromise,供handle函数改变待处理的Promise对象为bindPromise(回调函数传参的需要),并在handleResolved通过bindPromise的resovle、reject函数给回调函数传递参数,同时回调函数仍通过原始Promise的then方法以及返回值res的then方法设置,均不改变。
  2. 若为anotherPromise情况,实现功能为执行另一次延时,延时结束后再执行then方法注册的回调函数。执行过程中,再度使用doResolve函数执行anotherPromise的延迟函数anotherFn,并挂载回调函数的启动器内部resolve、reject函数,终止本次resolve函数执行,因此回调函数的触发时机为anotherFn延迟执行完毕、触发执行resolve或reject函数时。
  3. 若为普通传参。执行过程中,promise._81状态改写为1,即resolved执行成功状态,调用finale函数获取回调函数和返回值res,顺序执行handle、handleResolve函数,最终使当前Promise.then方法和返回值res.then注册的回调函数得到执行。
  • reject(promise,newValue)成功reject状态回调函数启动器,newValue通过外部函数获得或者由回调函数执行过程捕获的错误构成。执行过程中,promise._81状态改写为2,即rejected执行成功状态,调用finale函数获取回调函数和返回值res,顺序执行handle、handleResolve函数,最终使当前Promise.then方法和返回值res.then注册的回调函数得到执行。
  • finale(promise)通过promise._54获取由then方法注册的回调函数onFulfilled,onRejected、以及then方法返回res构成的handler对象,handler为数组形式,获取元素项逐个调用handle方法执行回调函数。待到回调函数执行完毕,清空promise._54。
  • Promise.then(onFulfilled,onRejected),分为this关键字有否遭改变的两种情况。
  1. 若this.constructor仍指向Promise构造函数,以空函数noop创建新的Promise对象res,并作为返回值,调用Handler构造函数生成挂载有回调函数onFulfilled,onRejected、以及res的handler对象,调用handle函数将该handler添加到promise._54中,以供延迟执行完毕后使用。
  2. 若this.constructor不指向Promise构造函数,调用safeThen函数,以空函数noop创建新的Promise对象res,并作为参数传入Handler构造函数中,以此实现设置两个回调函数的需求。延迟执行完成后,首先将执行onFulfilled、onRejected回调函数,再由这两个函数的返回值作为参数,执行外部回调函数resolve、reject,这两个函数在this.constructor实例中注册,this.constructor调用res.then(resolve,reject)以完成延时执行的需要
  • safeThen(this,onFulfilled,onRejected)函数,处理then方法this.constructor不指向Promise构造函数的情况,以空函数noop创建新的Promise对象res,并用res.then方法挂载this.constructor实例中传入的resolve、reject函数,且res作为参数传入Handler构造函数中,以使resolve、reject函数作为延迟执行完成后的回调函数。而原始then方法注册的onFulfilled、onRejected回调函数也作为参数传入Handler构造函数,因此onFulfilled、onRejected回调函数将作为过滤器处理外部函数fn中resolve、reject函数传递的参数,并将返回结果传递给this.constructor实例中的resolve、reject函数。
  • 构造函数Handler,存储当前Promise使用then方法注册的回调函数,以及关联的用空函数noop注册的Promise对象res,其或者作为then方法的返回值形成链式回调,或者作为两次回调函数实现的依赖条件。在then方法执行过程中,handler对象存储在promise._54中;在回调函数启动过程中,该handler对象从promise._54取出,以实现多次执行回调。
  • handle(promise,handler)函数,当then方法挂载回调函数执行该函数时,将构造函数Handler创建的handler添加到promise._54中,以供延迟执行完毕、回调函数启用过程中使用。当延时执行完毕,由finale函数调用该函数时,判断promise._81是否为adopted状态,需要以另一个Promise对象bindPromise的参数执行回调函数,将参数promise赋值为bindPromise,以供后续使用;顺序执行handleResolved函数,目的是执行回调函数onFulfilled,onRejected,以及其他链式注册的回调函数。
  • handleResolved(promise,handler)函数,通过handler获取回调函数onFulfilled,onRejected,以promise._65执行之,返回值作为参数执行res.then注册的回调函数。

图解:


 

源码:

'use strict';

var asap=require('asap/raw');

function noop(){}// 空函数

var LAST_ERROR=null;
var IS_ERROR={};

function getThen(obj){
    try{
        return obj.then;
    }catch(ex){
        LAST_ERROR=ex;
        return IS_ERROR;
    }
}

function tryCallOne(fn,a){
    try{
        return fn(a);
    }catch (ex){
        LAST_ERROR=ex;
        return IS_ERROR;
    }
}

function tryCallTwo(fn,a,b){
    try{
      fn(a,b);
    }catch(ex){
        LAST_ERROR=ex;
        return IS_ERROR;
    }
}

module.exports=Promise;

// 传入函数,构建Promise对象(延时执行的回调承诺)
function Promise(fn){
    if ( typeof this!=='object' ){
        throw new TypeError('Promises must be constructed via new');
    }
    if ( typeof fn!=='function' ){
        throw new TypeError('not a function');
    }

    // 初次创建的时候this._45为0,this._54为空,以赋值更新,
    // 调用一次then方法时this._45为1,this._54数组有一个元素,以push方法更新
    this._45=0;

    // 存储状态,0-pending,1-resovled,2-rejected,3-adopted外部函数fn中resovle函数获得参数为另一个Promise对象
    this._81=0;

    // 存储resovle、reject函数传递的参数,供回调函数onFulfilled,onRejected使用
    this._65=null;

    // 保存相关的Handler对象,存储有onFulfilled,onRejected回调函数,及then方法的返回值res
    this._54=null;

    if ( fn===noop ) return;// 引用地址相同

    // 将resovle、reject函数提供给模块外部函数fn
    doResolve(fn,this);
}

Promise._10=null;
Promise._97=null;
Promise._61=noop;

// then方法注册回调函数onFulfilled,onRejected
Promise.prototype.then=function(onFulfilled,onRejected){
    if ( this.constructor!==Promise ){
        return safeThen(this, onFulfilled, onRejected);
    }

    // 以noop空函数创建新的Promise对象,作为返回值获取后续注册的回调函数,供链式调用
    // 以noop创建Promise对象时,doResolve函数将不予执行
    var res=new Promise(noop);
    handle(this,new Handler(onFulfilled,onRejected,res));
    return res;
};

// promise(fn).then.call(Constructor,onFulfilled,onRejected)
// onFulfilled, onRejected回调执行完成后,在执行回调函数resolve,reject
function safeThen(self, onFulfilled, onRejected){
    return new self.constructor(function (resolve,reject){
        var res=new Promise(noop);
        res.then(resolve, reject);
        handle(self,new Handler(onFulfilled, onRejected, res));
    });
};

// deferred为Handler对象,存储有onFulfilled,onRejected回调函数
function handle(self,deferred){
    // 外部函数fn中resovle参数为promise,self改为该promise,以该promise向回调函数传参
    while ( self._81===3 ){
        self=self._65;
    }

    if ( Promise._10 ){// ???
        Promise._10(self);
    }

    // then方法初次调用时,promise._54添加相关Handler对象
    if ( self._81===0 ){
        // then方法的返回值是新的promise对象,
        if ( self._45===0 ){
            self._45=1;
            self._54=deferred;
            return;
        }
        if ( self._45===1 ){// 什么时候发生???
            self._45=2;
            self._54=[self._54,deferred];
            return;
        }
        self._54.push(deferred);
        return;
    }

    // 执行onFulfilled、onRejected回调
    handleResolved(self,deferred);
}

// deferred为Handler对象,存储有onFulfilled,onRejected回调函数
// deferred.promise为then方法中创建的Promise对象res,同时res作为返回值,拉取后续注册的回调函数
function handleResolved(self,deferred){
    asap(function(){
        var cb=self._81===1 ? deferred.onFulfilled : deferred.onRejected;
        if ( cb===null ){
          if ( self._81===1 ){
              resolve(deferred.promise,self._65);
          }else{
              reject(deferred.promise,self._65);
          }
          return;
        }
        var ret=tryCallOne(cb,self._65);// 执行回调
        if (  ret===IS_ERROR ){
            reject(deferred.promise,LAST_ERROR);
        }else{
            resolve(deferred.promise,ret);
        }
    });
}

// resovled状态回调函数的启动器
function resolve(self,newValue){
    // 外部函数fn所用参数不能为当前promise对象本身,实际上似乎也没有这个可能
    if ( newValue===self ){
        return reject( self,new TypeError('A promise cannot be resolved with itself.') );
    }

    // 外部函数fn中调用resovle携带的参数值newValue本身是一个promise对象或函数
    if ( newValue && (typeof newValue==='object' || typeof newValue==='function') ){
        var then=getThen(newValue);

        // newValue不是合格的promise对象,调用reject方法执行失败的回调函数
        if ( then===IS_ERROR ){
            return reject(self,LAST_ERROR);
        }

        // newValue是promise对象
        // 传参为bindPromise,且bindPromise.then=Promise.then,fn延时已执行,使用bindPromise的回调
        if ( then===self.then && newValue instanceof Promise ){
            self._81=3;// 执行状态为adopted
            self._65=newValue;
            finale(self);
            return;

        // 传参为anotherPromise,重新注册执行anotherPromise的延迟函数,完成后调用链式注册的回调
        }else if( typeof then==='function' ){
            doResolve(then.bind(newValue),self);
            return;
        }
    }
    self._81=1;// 执行状态为resovled
    self._65=newValue;// 缓存外部函数fn中调用resovle携带的参数值
    finale(self);
}

// rejected状态回调函数的启动器
function reject(self,newValue){
    self._81=2;// 执行状态为rejected
    self._65=newValue;// 缓存外部函数fn中调用resovle携带的参数值
    if ( Promise._97 ){
        Promise._97(self,newValue);
    }
    finale(self);
}

// 中间件,桥接resovle|reject-handle函数,根据当前promise对象相关Handler对象的数目执行handle函数
function finale(self){
    if ( self._45===1 ){
        handle(self,self._54);
        self._54=null;
    }
    if ( self._45===2 ){
        for ( var i=0; i<self._54.length; i++ ){
            handle(self,self._54[i]);
        }
        self._54=null;
    }
}

// 存储回调函数onFulfilled,onRejected和管理器promise
function Handler(onFulfilled,onRejected,promise){
    this.onFulfilled=typeof onFulfilled==='function' ? onFulfilled : null;
    this.onRejected=typeof onRejected==='function' ? onRejected : null;
    this.promise=promise;
}

// 将resovle、reject函数传给模块外部函数fn
function doResolve(fn,promise){
    var done=false;// 是否执行完毕

    var res=tryCallTwo(fn,function(value){
        if (done) return;
        done=true;
        resolve(promise,value);
    },function (reason){
        if (done) return;
        done=true;
        reject(promise,reason);
    })

    // fn执行报错,调用reject回调函数
    if ( !done && res===IS_ERROR ){
        done=true;
        reject(promise,LAST_ERROR);
    }
}

 

 

二、lib/done.js:Promise.prototype.done方法

Promise.prototype.done方法实现,调用then方法添加onFulfilled,onRejected,假使遭遇reject状态,添加抛出错误的回调函数。

'use strict';

var Promise=require('./core.js');

module.exports=Promise;
Promise.prototype.done=function (onFulfilled,onRejected){
	var self=arguments.length ? this.then.apply(this,arguments) : this;
	self.then(null, function (err){
	    setTimeout(function (){
	      throw err;
	    }, 0);
	});
};

 

 

三、lib/es6-extensions.js:ES6-Promise模块实现

 

ES6-Promise模块功能需求及实现

  • Promise.resolve(value)方法,返回作为参数value的Promise对象、或者以空函数noop创建新的Promise对象、或者将thenable对象转化为Promise对象(thenable对象的then方法立即执行),目的是为链式调用then方法注册的回调函数设置参数。
  • Promise.reject(value)方法,设置rejected状态的回调函数,并触发执行rejected状态的回调函数。回调将立即执行,因此reject方法的意义是个问题
  • Promise.prototype["catch"](onRejected),当前Promise用then方法加载onRejected回调函数,并返回以noop创建的新Promise对象。该方法在原型中,其他均在构造函数中,构成静态方法。
  • Promise.all方法,多个Promise对象或thenable对象(含有then方法的对象)同时启动,最后一个延时执行完成后,执行链式调用then方法注册的回调函数。实现功能同$.when().done()相似,实现原理也类同,通过创建新的Promise对象实现链式调用,通过闭包变量remaining判断各延时函数是否执行完毕。
  • Promise.then方法,多个Promise对象或thenable对象(含有then方法的对象)同时启动,第一个延时执行完成后,就立即执行链式调用then方法注册的回调函数。问题是,其他延时对象执行完成后,还是会调用回调函数,依赖于使用者对源码的理解。

源码:

'use strict';

// 浏览器端实现
//This file contains the ES6 extensions to the core Promises/A+ API

var Promise=require('./core.js');

module.exports=Promise;

/* Static Functions */

var TRUE=valuePromise(true);
var FALSE=valuePromise(false);
var NULL=valuePromise(null);
var UNDEFINED=valuePromise(undefined);
var ZERO=valuePromise(0);
var EMPTYSTRING=valuePromise('');

// 以空函数noop创建Promise对象res,设置回调函数的参数
// 其他函数中调用该函数构成链式调用then方法的需要,主要目的是设置回调的参数
function valuePromise(value) {
    var p=new Promise(Promise._61);// 以空函数noop创建Promise对象
    p._81=1;// promise状态,pending、resolved、rejected、adopted
    p._65=value;// 回调函数参数
    return p;
}

// 返回新创建的Promise对象,以供链式调用then方法注册回调,并设置回调的参数
Promise.resolve=function(value){
    if (value instanceof Promise) return value;

    if (value===null) return NULL;
    if (value===undefined) return UNDEFINED;
    if (value===true) return TRUE;
    if (value===false) return FALSE;
    if (value===0) return ZERO;
    if (value==='') return EMPTYSTRING;

    // 将带有then方法的thenable对象转化为Promise对象,立即执行thenable对象的then方法
    if ( typeof value==='object' || typeof value==='function' ){
        try{
            var then=value.then;
            if ( typeof then==='function' ){
                return new Promise(then.bind(value));
            }
        }catch(ex){
            return new Promise(function (resolve,reject){
                reject(ex);
            });
        }
    }

    return valuePromise(value);
};

// 多个延时对象Promise或thenable合并为一个Promise,几个延时对象同时启动,最后一个执行完成后执行回调
// 实现功能和$.when().then()相仿
Promise.all=function (arr){
    var args=Array.prototype.slice.call(arr);

    return new Promise(function (resolve,reject){
        if ( args.length===0 ) return resolve([]);
        var remaining=args.length;

        function res(i,val){
            if (val && (typeof val==='object' || typeof val==='function') ){
                if ( val instanceof Promise && val.then===Promise.prototype.then ){
                    while ( val._81===3 ){
                        val=val._65;
                    }
                    if ( val._81===1 ) return res(i,val._65);
                    if ( val._81===2 ) reject(val._65);
                    val.then(function (val){
                        res(i,val);// val不是Promise对象或thenable对象时,将参数转交给args
                    },reject);
                    return;
                }else{
                    // thenable对象时,直接执行thenable的then方法
                    var then=val.then;
                    if ( typeof then==='function' ){
                        var p=new Promise(then.bind(val));
                        p.then(function (val) {
                            res(i, val);
                        }, reject);
                        return;
                    }
                }
            }
            args[i]=val;
            if ( --remaining===0 ){// 延迟函数都执行完毕后,执行新建Promise对象的回调,传参由各延时构成
                resolve(args);
            }
        }

        for (var i=0; i<args.length; i++){
            res(i,args[i]);
        }
    });
};

// 设置rejected状态回调函数的参数,并触发rejected状态回调函数
Promise.reject=function (value){
    return new Promise(function (resolve,reject){
        reject(value);
    });
};

// 同时执行的延时对象,当第一个延时执行完成,即执行回调函数,没有解决其他延时执行后调用回调的问题
Promise.race=function (values){
    return new Promise(function (resolve,reject){
        values.forEach(function(value){
            Promise.resolve(value).then(resolve,reject);
        });
    });
};

// 报错时执行onRejected回调
Promise.prototype['catch']=function (onRejected){
    return this.then(null, onRejected);
};

 

 

 四、lib/finally.js-Promise.prototype.finally方法实现

Promise.prototype.finally(f)方法实现,若f函数返回值为Promise对象,延时完成后,回调函数的参数取原始Promise对象提供的参数;f返回值为其他,通过Promise.resolve方法构建Promise对象。因此finally方法执行延时,保持原有参数,实现的功能需要通过finally方法返回值Promise对象调用then方法注册回调函数,在回调函数中起作用,具体意义还是个问题。

 

'use strict';

var Promise=require('./core.js');

module.exports=Promise;

// f函数返回值为Promise对象时,延时完成后,将原始Promise对象的参数传递给后续注册的回调函数
Promise.prototype['finally']=function (f){
  	return this.then(function (value){
	    return Promise.resolve(f()).then(function (){
	      	return value;
	    });
  	}, function (err){
	    return Promise.resolve(f()).then(function (){
	      	throw err;
	    });
  	});
};

 

 

五、lib/synchronous.js:获取延迟状态、获取回调参数方法

  • Promise.enableSynchronous方法,执行后,使获取延迟状态、获取回调参数各方法可用。
  • Promise.disableSynchronous方法,执行后,将获取延迟状态、获取回调参数各方法设为undefined。
  • Promise.prototype.getState方法,获取执行状态0-pending、1-resolved、2-rejected,当遇到3-adopted状态时,获取关联Promise对象bindPromise的状态。
  • Promise.prototype.isPending方法是否执行中状态。
  • Promise.prototype.isFulfilled方法是否执行成功状态。
  • Promise.prototype.isRejected方法是否执行失败状态。
  • Promise.prototype.getValue方法获取resolved状态传参value。
  • Promise.prototype.getReason方法获取rejected状态传参reason。
'use strict';

var Promise=require('./core.js');

module.exports=Promise;

// 静态方法enableSynchronous使获取状态、获取传参方法可用
Promise.enableSynchronous=function (){
    Promise.prototype.isPending=function(){
      return this.getState()==0;
    };

    Promise.prototype.isFulfilled=function(){
      return this.getState()==1;
    };

    Promise.prototype.isRejected=function(){
      return this.getState()==2;
    };

    // 获取resolved状态传参value
    Promise.prototype.getValue=function (){
        if ( this._81===3 ){
            return this._65.getValue();
        }

        if ( !this.isFulfilled() ){
            throw new Error('Cannot get a value of an unfulfilled promise.');
        }

        return this._65;
    };

    // 获取rejected状态传参reason
    Promise.prototype.getReason=function (){
        if ( this._81===3 ){
            return this._65.getReason();
        }

        if ( !this.isRejected() ){
            throw new Error('Cannot get a rejection reason of a non-rejected promise.');
        }

        return this._65;
    };

    // 获取状态
    Promise.prototype.getState=function (){
      if ( this._81===3 ){
          return this._65.getState();
      }
      if ( this._81===-1 || this._81===-2 ){
          return 0;
      }

      return this._81;
    };
};

// 静态方法disableSynchronous使获取状态、获取传参方法不可用
Promise.disableSynchronous=function(){
    Promise.prototype.isPending=undefined;
    Promise.prototype.isFulfilled=undefined;
    Promise.prototype.isRejected=undefined;
    Promise.prototype.getValue=undefined;
    Promise.prototype.getReason=undefined;
    Promise.prototype.getState=undefined;
};

 

六、lib/node-extensions.js 暂缺 

 

猜你喜欢

转载自schifred.iteye.com/blog/2317978
今日推荐