一、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方法,以及仅仅是普通的参数。
- 若为bindPromise情况,实现功能为用bindPromise向回调函数传参。执行过程中,promise._81状态改写为3,即adopted使用另一个Promise的回调,promise._65记录bindPromise,供handle函数改变待处理的Promise对象为bindPromise(回调函数传参的需要),并在handleResolved通过bindPromise的resovle、reject函数给回调函数传递参数,同时回调函数仍通过原始Promise的then方法以及返回值res的then方法设置,均不改变。
- 若为anotherPromise情况,实现功能为执行另一次延时,延时结束后再执行then方法注册的回调函数。执行过程中,再度使用doResolve函数执行anotherPromise的延迟函数anotherFn,并挂载回调函数的启动器内部resolve、reject函数,终止本次resolve函数执行,因此回调函数的触发时机为anotherFn延迟执行完毕、触发执行resolve或reject函数时。
- 若为普通传参。执行过程中,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关键字有否遭改变的两种情况。
- 若this.constructor仍指向Promise构造函数,以空函数noop创建新的Promise对象res,并作为返回值,调用Handler构造函数生成挂载有回调函数onFulfilled,onRejected、以及res的handler对象,调用handle函数将该handler添加到promise._54中,以供延迟执行完毕后使用。
- 若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 暂缺
相关推荐
Promise模块在JavaScript中扮演着异步编程的核心角色。Promise是一种处理异步操作的方法,它代表了一个将来可能完成或失败的任务,允许我们以一种更有序、更易于理解和维护的方式来编写复杂的异步代码。Promise有三...
1. **Promise化API**:sander将所有fs模块的方法包装成返回Promise的对象,这样可以利用Promise的链式调用来处理异步操作,避免了回调地狱,使代码结构更加清晰。 2. **错误处理**:在Promise的reject中处理错误,...
本文将深入探讨“模块间通信源码”,并基于提供的RPCTest资源来解析这一主题。 模块化编程是现代软件工程的基础,通过将大项目分解为小而独立的模块,可以提高代码的可读性、可维护性和复用性。模块间通信(Inter-...
在这个“NodeJS C++,打印机模块源码”项目中,开发人员编写了一个C++模块,该模块被包装成NodeJS的addon,以便在NodeJS或Electron环境中使用。C++是底层系统编程的强大工具,能够直接访问操作系统的API,如Windows的...
Promise.js 的使用对任何Web开发者来说都是一个重要的技能,它能够帮助你编写更加模块化、易于理解和维护的异步代码。在现代前端开发中,Promise已经成为了处理异步操作的标准工具,掌握Promise.js 的使用将极大地...
- **加载远程入口**:通过 `webpack.container.loadRemoteEntry()` 加载子应用的远程入口,这个函数会返回一个 Promise,等待远程模块加载完成。 - **注入远程模块**:加载完成后,我们可以使用 `webpack.container...
JavaScript是Web开发中...通过对这些模块源码的深入学习和实践,不仅可以掌握JavaScript的核心概念,还能提升实际项目中的编程能力。同时,这也会帮助你更好地理解和适应JavaScript生态系统中不断发展的新特性和工具。
6. **兼容性**:`stream-promise`设计时考虑了浏览器兼容性,确保在多种现代浏览器上都能正常工作,同时也支持使用`browserify`或`webpack`等打包工具进行模块化构建。 7. **API设计**:`stream-promise`的API设计...
通过创建一个独立的`db.js`文件来封装连接逻辑,我们可以轻松地在多个模块中重用数据库连接,并且使用Promise和async/await语法使得代码更加简洁、易于理解。同时,每个特定数据库操作的模块(如`users.js`)只关注...
在JavaScript的世界里,Promise是处理异步操作的重要工具,它提供了链式调用的方式来优雅地管理异步代码。然而,Promise的一个常见最佳实践是确保每个Promise链都有对应的`catch`语句来捕获并处理可能出现的错误。这...
JavaScript中的Promise是异步编程的关键工具,用于管理...Promise的这些特性使得异步编程更加模块化和易于管理。通过理解Promise的工作原理和正确使用其方法,开发者可以编写出更加整洁、易于维护的JavaScript代码。
2. **Node.js的子进程(Child Process)模块**: Node.js 提供了子进程模块,可以创建和管理子进程,如`child_process.fork()`,它允许我们在子进程中执行Node.js脚本。这样我们可以在不同的进程中运行计算任务,避免...
为了解决这个问题,我们可以将uni.request封装在一个返回Promise的函数里,这样就可以利用async/await语法来简化异步代码。 async/await是ES2017引入的新特性,它提供了更接近同步编程的语法糖。async函数会返回一...
这个压缩包“完整版目标目录选择框模块代码.rar”包含了实现这一功能的源代码,下面将详细解释相关知识点。 1. **目录选择框**: - 目录选择框是用户界面(UI)设计中的一个重要元素,允许用户在一系列层级结构中...
本项目 "前端项目-native-promise-only" 集中关注了 Promise 的本地实现,名为 "native-promise-only",旨在提供一个纯净的 Promise 模块,仅包含 ES6 规范中的 Promise 功能,没有额外的库或依赖。 在 ES6 中,...
在`wx_network-master`这个压缩包中,可能包含了封装好的网络请求库源代码,包括模块化的组织方式,以及可能的测试用例。开发者可以通过阅读源代码,了解如何将Promise与微信小程序的网络请求接口结合,以提高代码...
基于fetch ,加载的模块如果不同域,则必须支持跨域请求,因为要使用模块的源代码来生成包装函数 使用http响应headers中的content-type属性来判断是json还是JavaScript模块 headers中的content-type属性必须为...
6. **模块化**:作为NPM包发布,`node-promise`遵循Node.js的模块化规范,可以方便地通过`require`引入到项目中。 标签“前端开源”表明这个库是面向前端开发者开放的,可以自由使用、修改和分发,遵循开源许可证。...
3. **ECMAScript支持**:ECMAScript(ES)是JavaScript的标准化规范,源码可能使用了ES6及以上版本的语法特性,如箭头函数、模板字符串、Promise等,提高代码的可读性和简洁性。 4. **前端开发**:作为前端功能模块...
为了解决这个问题,出现了`superagent-es6`这个npm模块,它为Superagent添加了Promise支持,使其与ES6的语法风格更加契合。 **ES6 Promise概述** ES6 Promise是JavaScript中处理异步操作的一种方式,它提供了一种...