当前位置: 首页 > Web前端 > HTML

自己实现一个Promise

时间:2023-04-02 18:18:51 HTML

PromisePromise鏄疎S6涓紓姝ョ紪绋嬬殑涓€绉嶈В鍐虫柟妗堬紝姣斾紶缁熺殑瑙e喅鏂规鈥斺€斿洖璋冨嚱鏁板拰浜嬩欢鏇村悎鐞嗐€佹洿寮哄ぇ銆侾romise鏄竴涓璞★紝鎻愪緵浜嗙粺涓€鐨凙PI锛屽悇绉嶅紓姝ユ搷浣滃彲浠ョ敤鍚屾牱鐨勬柟寮忓鐞嗐€侾romise鎿嶄綔鍙細澶勪簬涓夌鐘舵€佷箣涓€锛氬緟澶勭悊銆佸凡瑙e喅鍜屽凡鎷掔粷銆侾romise鐨勭姸鎬佸彧浼氫粠鏈畬鎴愮姸鎬佸彉涓哄畬鎴愮姸鎬佹垨澶辫触鐘舵€併€傜姸鎬佷竴鏃﹁浆鍙橈紝灏辨棤娉曟敼鍙樸€傛洿澶歅romise鍩虹鐭ヨ瘑璇疯烦杞埌闃竴宄?Es6Promise鎵嬪姩瀹炵幇涓€涓狿romise杩欏勾澶达紝鎵嬪姩瀹炵幇涓€涓狿romise宸茬粡鏄潰璇曠殑甯歌鎿嶄綔浜嗐€傛帴涓嬫潵锛屼负浜嗘洿濂界殑鐞嗚ВPromise锛屾垜浠氨鏉ealize瀹冿紱Promise鏈夌粺涓€鐨勮鑼冿紝鐩殑鏄负浜嗚澶у瀹炵幇鐨刾romise鏇村ソ鐨勫疄鐜板吋瀹规€э紝鎵€浠ュ嚭鐜颁簡Promises/A+瑙勮寖锛涙帴涓嬫潵鐨刾romises閮芥槸鎸夌収Promises/A+瑙勮寖瀹炵幇鐨凱romises鍥犱负绫绘湁涓夌鐘舵€侊紝鎵€浠ュ厛澹版槑涓変釜甯搁噺鏉ヨ〃绀虹姸鎬乧onstPENDING='pending';constFULFILLED='宸插畬鎴?;constREJECTED='鎷掔粷';鍐欎竴涓狿romise绫籧lassPromise{constructor(executor){//褰㈠紡鍙傛暟楠岃瘉if(typeofexecutor!=='function')thrownewTypeError(`Promiseresolver${executor}isnotafunction`)//鍒濆鍖栬繖涓€傜姸鎬?寰呭鐞嗭紱//鐘舵€乼his.value=null;//鏈€缁堝€紅his.reason=null;//鎷掔粷鍘熷洜//鎵цcbexecutor();}}鐒跺悗鎴戜滑闇€瑕佸湪Promise鐨勫舰鍙傛墽琛屽櫒涓坊鍔爎esolve鍜宺eject涓や釜褰㈠弬鍑芥暟锛涙牴鎹畾涔夛紝瀹冧滑鏄敱JS寮曟搸鎻愪緵鐨勶紝鎵€浠ユ垜浠渶瑕佹彁鍓嶅畾涔塩lassPromise{constructor(executor){...//bindthisinresolveandrejecttothePromiseinstance+this.resolve=this.瑙e喅.bind(this);+this.reject=this.reject.bind(this);//executecb+try{+executor(this.resolve,this.reject);+}catch(e){this.reject(e)}}resolve(val){//鍒ゆ柇褰撳墠鐘舵€侊紝鍙兘鎵ц澶勪簬绛夊緟鐘舵€乮f(this.status===PENDING){this.status=FULFILLED;//鐘舵€佹敼鍙榯his.value=val;//鏈€缁堣祴鍊紏}reject(err){if(this.status===PENDING){this.status=REJECTED;this.reason=閿欒锛泒}}褰損romise瀹炰緥璋冪敤鍐呴儴鍑芥暟resolve鎴杛eject鏃讹紝璋冪敤鐨勫叾瀹炴槸涓€涓尶鍚嶅嚱鏁帮紝鏃犳硶鑾峰彇鍑芥暟涓璽his.status鐨勫€硷紝鎵€浠ラ渶瑕佹彁鍓嶇敤bind杩涜缁戝畾锛涘綋promise瀹炰緥鐨勬墽琛岃€呮湰韬姏鍑哄紓甯告椂锛孭romise浼氬皢寮傚父鏀惧叆reject鍑芥暟涓幓澶勭悊锛屾墍浠ユ坊鍔爐ry{...}catch(e){...}鏉ュ鐞嗚繖绉嶆儏鍐点€傚垵姝ュ疄鐜扮劧鍚庢帴鏀朵袱涓洖璋冨嚱鏁般€俹nFulfilled鏄綋promise瀹炰緥鐨勭姸鎬佸彉涓篺ulfilled鏃惰皟鐢ㄧ殑鍑芥暟銆俹nRejected鏄疄渚嬬姸鎬佸彉涓烘嫆缁濇椂璋冪敤鐨勫嚱鏁帮紝鐒跺悗杩斿洖涓€涓柊鐨刾romise瀹炰緥锛涜繖閲屼娇鐢╯etTimeout鏉ユā鎷烶romise閲岄潰鐨勫井浠诲姟寮傛绫籔romise{...then(onFulfilled,onRejected){//鍙傛暟妫€鏌nFulfilled,onRejected鏄彲閫夌殑褰㈠弬onFulfilled=typeofonFulfilled!=='function'?val=>val:onFulfilled;onRejected=typeofonRejected!=='鍑芥暟'?鍘熷洜=>{鎶涘嚭鍘熷洜}:onRejected;if(this.status===FULFILLED){//setTimeout妯℃嫙寰换鍔″紓姝etTimeout(()=>{try{//閲嶆柊鍔犲叆try-catch锛宻ettimeout鏄紓姝ョ殑锛屼笉鑳借閲岄潰鐨則ry-catch鎹曡幏澶栭儴鏋勯€犲嚱鏁皁nFulfilled(this.value);//浠ユ渶缁堝€间綔涓哄弬鏁版墽琛宱nFulfilled鍑芥暟}catch(e){reject(e)}})}if(this.status===REJECTED){//鎵цonRejected鍑芥暟setTimeout(()=>{try{onRejected(this.reason);}catch(e){reject(e)}});}}}then淇敼鏍规嵁涓婇潰鐨勫啓娉曪紝濡傛灉resolve鍦ㄦ垜浠琾romise瀹炰緥鐨別xecutor涓槸寮傛瀹炵幇锛岄偅涔坱hen鏂规硶灏变笉鑳借揪鍒板師鏉ョ殑鏁堟灉newPromise((resolve,reject)=>{setTimeout(()=>{resolve(1)})}).then(val=>console.log(val),//output1err=>console.log(err))姝ゆ椂鎴戜滑鑷繁鐨刾romise渚嬪瓙鏃犳硶姝g‘杈撳嚭1銆傚師鍥犳槸褰撳紓姝ユ墽琛屾墽琛屽櫒涓殑鐘舵€佹敼鍙橈紙resolve/reject锛夋椂锛屽悓姝ヨ皟鐢ㄤ簡then鍑芥暟銆傛鏃秔romise鐨勭姸鎬佽繕鏄痯ending鐘舵€侊紝涓嶈兘璋冪敤浠讳綍鍑芥暟锛涙墍浠ユ垜浠湁蹇呰鍦╰hen涓姞鍏ending鐘舵€佺殑澶勭悊锛涢噰鐢ㄨ闃呭拰鍙戝竷鐨勬柟寮忚В鍐崇姸鎬佸紓姝ュ彉鍖朿lassPromise{constructor(executor){...//鍒濆鍖?..+this.onFulfilledCbs=[];//鎴愬姛鍥炶皟鍑芥暟queue+this.onRejectedCbs=[];//澶辫触鍥炶皟鍑芥暟闃熷垪...}resolve(val){if(this.status===PENDING){...//涓€鏃︾姸鎬佹敼鍙橈紝閬嶅巻鍑芥暟闃熷垪锛屼互鏈€缁堝€间綔涓哄弬鏁拌Е鍙戦槦鍒椾腑鐨勫嚱鏁?this.onFulfilledCbs.forEach(fn=>fn(this.value));}}reject(err){if(this.status===PENDING){...+this.onRejectedCbs.forEach(fn=>fn(this.reason));}}then(onFulfilled,onRejected){...//褰撶姸鎬佷负pending+if(this.status===PENDING){+//娣诲姞寰换鍔″洖璋冨嚱鏁板埌鍑芥暟闃熷垪+this.onFulfilledCbs.push(value=>{+setTimeout(()=>{+try{+onFulfilled(value)+}catch(e){reject(e)}+})+});++this.onRejectedCbs.push((鍘熷洜)=>{+setTimeout(()=>{+try{+onRejected(reason)+}catch(e){reject(e)}+})+});+}}}杩欐牱褰損romise瀹炰緥鐨勭姸鎬佸紓姝ユ洿鏀癸紝鐒跺悗鏄柟娉曚篃鑳芥纭Е鍙戦摼寮忚皟鐢ㄣ€備箣鍓嶈杩囷紝then鏂规硶浼氳繑鍥炰竴涓柊鐨刾romise瀹炰緥锛岃繖涓疄渚嬬殑鍊煎彲浠ラ€氳繃then鏃犻檺璋冪敤鏃犻檺浼犻€掍笅鍘汇€備负浜嗗疄鐜拌繖涓柟娉曪紝鎴戜滑闇€瑕佸湪then涓繑鍥炰竴涓猵romiseNewpromiseinstancethen(onFulfilled,onRejected){...//鍒涘缓涓€涓柊鐨刾romise瀹炰緥+letpromise2=newPromise((resolve,reject)=>{//鍚屾鎿嶄綔锛堝垵濮嬬姸鎬佸彉涓哄悓姝ワ級if(this.status===FULFILLED){...}if(this.status===REJECTED){...}if(this.status===PENDING){...}+})+returnpromise2}閭f垜浠湪鏂扮殑promise2涓€庝箞璋冪敤resolve鍜宺eject鍛紵鏈畾锛屽弬鑰冭鑼冩牴鎹甈romises/A+瑙勮寖锛屾垜浠皢onFulfilled(value)鍜宱nRejected(reason)鐨勭粨鏋滃畾涔変负x锛屽皢鍏跺拰promise2浼犲叆涓€涓柊鍑芥暟resolvePromise杩涜澶勭悊锛涜繖閲屾垜浠娇鐢ㄨ繖涓猲ew澶勭悊鍑芥暟瀹氫箟涓哄父閲忓嚱鏁?/@params//$pomise2-newpromise甯搁噺//$x-onFulfilled/onRejected澶勭悊缁撴灉//$resolve-resolvefunctioninpromise2//$reject-rejectfunctionconstinpromise2RESOLVEPROMISE=function(promise2,x,resolve,reject){...}鐒跺悗閲嶅啓then鏂规硶then(onFulfilled,onRejected){...//杩斿洖涓€涓柊瀹炰緥瀹炵幇閾惧紡璋冪敤letpromise2=newPromise((resolve,reject)=>{if(this.status===FULFILLED){setTimeout(()=>{try{//浠ユ渶缁堝€间綔涓哄弬鏁版墽琛宱nFulfilled鍑芥暟+letx=onFulfilled(this.value);//鍒嗘瀽鎵ц缁撴灉x涓巔romise鐨勫叧绯?RESOLVEPROMISE(promise2,x,resolve,reject);}catch(e){reject(e)}})}if(this.status===REJECTED){setTimeout(()=>{try{+璁﹛=onRejected(this.reason)+RESOLVEPROMISE(promise2,x,resolve,reject);}catch(e){reject(e)}});}if(this.status===PENDING){this.onFulfilledCbs.push(value=>{setTimeout(()=>{try{+letx=onFulfilled(value)+RESOLVEPROMISE(promise2,x,resolve,reject);}catch(e){reject(e)}})});this.onRejectedCbs.push((reason)=>{setTimeout(()=>{try{+letx=onRejected(reason)+RESOLVEPROMISE(promise2,x,resolve,reject);}catch(e){reject(e)}})});}})returnpromise2}瀹炵幇resolvePromise鍑芥暟鏍规嵁瑙勮寖锛宺esolvePromise瑙勫垯澶ц嚧濡備笅锛歱romise2鍜寈鎸囧悜鍚屼竴涓璞★紝鎶涘嚭绫诲瀷閿欒銆傚鏋渪鏄疨romise绫伙紝鍒欏畠鐨勭姸鎬佽鎺ュ彈銆傚苟鐩稿簲鐨勬墽琛屽叾resolve鎴杛eject鍑芥暟x鏄嚱鏁版垨瀵硅薄x.then鏄嚱鏁帮紝璋冪敤x.then鏂规硶锛岄€掑綊缁撴灉x.then涓嶆槸鍑芥暟锛岃皟鐢ㄤ笂闈㈢殑resolve涓嶆槸锛岃皟鐢╮esolveconstRESOLVEPROMISE=function(promise2,x,resolve,reject){//x绛変簬promise2->鎶ュ憡閿欒if(promise2==x){returnreject(newTypeError('Chainingcycledetectedforpromise'))}letcalled;//闃叉澶氭鎴愬姛璋冪敤鍜屽け璐?/x鏄竴涓猵romise绫籭f(xinstanceofPromise){x.then(value=>{Promise.resolvePromise(promise2,value,resolve,reject);},err=>{reject(err)})//x鏄嚱鏁拌繕鏄璞elseif(x!==null&&typeofx=='object'||typeofx=='function'){try{//鍙杧.then鍙兘鎶ラ敊//ifxhasthen鏂规硶letthen=x.then;//ifthen鏄竴涓嚱鏁癷f(typeofthen=='function'){//浣跨敤call璋冪敤then鏂规硶鎸囧悜x锛岄槻姝㈠啀娆″彇x.then鎶ラ敊then.call(x,value=>{if(called)return;called=true;Promise.resolvePromise(promise2,value,resolve,reject);},err=>{if(called)return;called=true;reject(err)})//then涓嶆槸鍑芥暟}else{if(called)return;绉颁负=鐪燂紱瑙e喅锛坸锛夛紱}}catch(e){if(called)returncalled=truereject(e)}}else{//x涓哄熀鏈被鍨嬪€紃esolve(x);}}鑷虫锛屾垜浠殑Promise灏卞熀鏈疄鐜颁簡锛岄櫎浜唗hen鏂规硶浠ュ鐨勬柟娉曡繖閲屽氨涓嶄竴涓€瀹炵幇浜嗭紱鍙互鍏ㄥ眬瀹夎涓€涓彃浠讹紝娴嬭瘯鑷繁瀹炵幇鐨凱romise鏂囦欢鏄惁绗﹀悎瑙勮寖npminstall-gpromises-aplus-tests鐒跺悗鍦ㄦ枃浠舵湯灏炬坊鍔狅紝鍙傝€冩彃浠舵帴鍙i獙璇丳romise.defer=Promise.deferred=function(){letdfd={};dfd.promise=newPromise((resolve,reject)=>{dfd.resolve=resolve;dfd.reject=reject;})returndfd;}module.exports=Promise;鏈€鍚庡湪缁堢杈撳叆鍛戒护鏌ョ湅鏂囦欢promises-aplus-tests[[浣犵殑Promise鏂囦欢鍚?js]]婧愮爜娆㈣繋绉绘鏈枃婧愮爜鏈€鍚庨檮涓婁竴涓鍚圥romise鐨凱romise/A+瑙勮寖瀹炵幇銆傚笇鏈涜兘甯姪澶у鏇存竻妤氱殑浜嗚ВPromise銆傛劅璋㈤槄璇伙紝娆㈣繋鎸囨銆傝璁吼煒€鍚勪綅璇昏€咃紝娆㈣繋star馃専