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

高级javaScript---《手写 Promise(后篇)》

时间:2023-03-28 14:04:05 HTML

鍓嶈█锛氭渶鍚庝竴绔犵粓浜庢潵浜嗐€備笉鐭ラ亾鏈夋病鏈変汉鐪熸璺熻繘杩欎釜杩涢樁绯诲垪銆傛湰鏉ユ垜鐨勬剰鍥惧彧鏄洿鎺ヤ粠銆婃墜鎾?Promise銆嬪紑濮嬨€備絾鏄垜杞康涓€鎯筹紝杩欏涓€浜涘熀纭€鐭ヨ瘑涓嶆槸鐗瑰埆鎵庡疄鐨勫皬浼欎即鏉ヨ涓嶆槸寰堝弸濂斤紝鎵€浠ユ垜鍒涘缓浜嗚繖涓笓鏍忥紝璇曞浘浠庡ご寮€濮嬪憡璇夐偅浜涚湡姝f兂浠庢垜鐨勫崥鏂囦腑瀛﹀埌寰堝涓滆タ鐨勪汉.闃呰鏈枃鍓嶏紝浣犻渶瑕佹帉鎻¢€氬叧鍓嶅叚澶т换鍔$殑閽ュ寵馃攽(0/6)鍔犳繁瀵笿S浠g爜杩愯鏈哄埗鐨勭悊瑙f墜鍐欌€滃洖璋冨湴鐙扁€濆畯浠诲姟鍜屽井浠诲姟鎵嬪啓Promise锛堜笂锛夋墜鍐欐壙璇猴紙涓嬶級璇锋寜鐓ф湰鏂囧畬鎴愪綘鍗囧ぉ鐨勬渶鍚庝竴姝ャ€?.鍒嗘瀽MyPromise瀛樺湪鐨勯棶棰樺鏋滀綘鎸夌収涓婁竴绡囨枃绔犵殑鐭ヨ瘑璺熻繘锛屼綘鐜板湪鐨勪唬鐮佸簲璇ユ槸杩欐牱鐨勩€傝櫧鐒剁湅璧锋潵宸茬粡瀹炵幇浜嗗瓨鍌ㄥ悓姝ユ暟鎹殑鍔熻兘锛屼互鍙婂瓨鍌ㄥ紓姝ユ暟鎹殑鍔熻兘锛屼絾鏄埌鐩墠涓烘锛屾垜浠殑MyPromise浠嶇劧鏄竴涓亣鐨凱romise銆備綘鏄粈鈥嬧€嬩箞鎰忔€濓紵璁╂垜浠湅鐪嬪師濮嬬殑Promise鍦ㄥ瓨鍌ㄥ悓姝ユ暟鎹椂鏄粈涔堟牱瀛愮殑銆傛牴鎹箣鍓嶇殑鐭ヨ瘑锛屼富绾跨▼涓婄殑console.log锛?鎴戝湪涓荤嚎绋嬩笂锛屾垜搴旇绗竴涓墽琛?锛夎偗瀹氫細姣擯romise瀹炰緥鐨則hen鏂规硶鐨刢onsole.log鎵ц寰楁洿蹇紝鍥犱负涓€涓湪涓荤嚎绋嬩笂锛屽彟涓€涓繕鍦╩icrotask闃熷垪涓紝鎴戜滑瑕佹帓闃熶竴娈垫椂闂淬€傛垜浠彲浠ュ緢蹇緱鍑虹粨璁猴紝鎺у埗鍙颁腑鐨勭粨鏋滃簲璇ユ槸杩欐牱鐨勶細鐜板湪璁╂垜浠祴璇曚竴涓嬫垜浠垰鍒氱紪鍐欑殑MyPromise鐨勬儏鍐垫槸浠€涔堟牱鐨勩€傚鏋滄垜浠殑MyPromise鏄悊鎯崇姸鎬佺殑鏁堟灉锛宺esolve鏂规硶搴旇琚斁鍏ュ井浠诲姟闃熷垪涓€傛墍浠ヤ笅闈㈢殑浠g爜鐞嗘兂鎯呭喌涓嬪簲璇ヨ緭鍑篶onsole.log杩欒浠g爜锛堟垜搴旇鏄涓€娆℃墽琛岋級锛岀劧鍚庤緭鍑烘暟瀛?銆傜劧鑰岋紝缁撴灉But:WhatshouldIdo锛燄煠?.microtasks鐨勫垱寤哄鏋滀綘涔嬪墠浠旂粏鐪嬭繃鎴戠殑鏂囩珷銆婂畯浠诲姟鍜屽井浠诲姟銆嬶紝閭d綘涓€瀹氱煡閬撳垱寤轰竴涓猰icrotasks鍏跺疄闈炲父闈炲父绠€鍗曘€傛病閿欙紝灏辨槸浣跨敤浜唚indow瀵硅薄涓婄殑queueMicrotask鍑芥暟銆傚氨杩欎箞骞插惂锛屾垜浠粠鍝噷璇诲彇鎴戜滑鐨勬暟鎹憿锛熶綘鏄惁璁板緱锛熶笉璁板緱浜嗭紝鎻愰啋涓€涓嬶紝搴旇鏄湪then鏂规硶鐨勭涓€涓洖璋冨嚱鏁皁nFulfilled鍑芥暟閲屽惂锛熻繖涓嶆槸寰堢畝鍗曞悧锛熷綋鎴戠洿鎺ュ湪state==='fulfilled'鐨勬椂鍊欙紝涔熷氨鏄暟鎹~婊″悗锛屾垜鎶妎nFulFilled鍑芥暟浠庡師鏉ョ殑鍚屾鎵ц浠g爜閫昏緫鏀规垚鏀惧埌microtask闃熷垪涓墽琛屻€傚摝锛屽浜嗭紝鍒繕浜嗘垜浠殑resolve鍑芥暟杩樻墽琛屼簡涓€涓壒娈婄殑onFulfilled鍑芥暟銆傛墍浠ヨ繖閲屼篃鏄竴鏍凤紝鎶婅鍙栨暟鎹殑浠诲姟鏀惧埌microtask闃熷垪涓墽琛屻€傝繖涓椂鍊欐垜浠潵娴嬭瘯涓€涓嬶紝鐪嬬湅鏄笉鏄垜浠兂鐨勯偅鏍枫€備互涓婃槸淇濆瓨鍚屾鏁版嵁鐨勬儏鍐碉紝鎴戜滑鏉ユ祴璇曚竴涓嬩繚瀛樺紓姝ユ暟鎹殑鎯呭喌銆傝繖鏄帶鍒跺彴杈撳嚭锛氬畬缇庯紒灏辨槸鎴戜滑瑕佽揪鍒扮殑鏁堟灉~3.澶氭璋冪敤then鏂规硶鐨勭粨鏋滐紝鎴戜滑鐨凪yPromise濂藉儚鏈夐偅绉嶅懗閬撱€備絾鏄鎴戜滑鍒嗘瀽涓€涓嬩笅闈㈢殑鎯呭喌銆傛垜浠繕鏄粠鍘熺敓鐨凱romise鏉ユ帹鏂€傛敞鎰忥紒杩欎笉鏄痶hen鏂规硶鐨勯摼寮忚皟鐢紝鑰屾槸瀵逛竴涓狿romise瀹炰緥澶氭璋冪敤then鏂规硶鐨勪竴绉嶆柟寮忋€傦紙杩欓噷涓嶈鍜岄摼寮忚皟鐢ㄦ悶娣蜂簡锛夋垜浠湅涓€涓嬫帶鍒跺彴鐨勬儏鍐碉細鍙互鐪嬪埌鎴戜滑鎵ц浜?娆hen鏂规硶锛屽畠浼氬府鎴戜滑鎵ц3娆¤鍙栨暟鎹殑鎿嶄綔銆備絾鏄浆杩囪韩鏉ョ湅鐪嬫垜浠殑MyPromise鍋氫簡浠€涔堛€傛寜鐓ф垜浠悊鎯崇殑鏁堟灉锛屾帶鍒跺彴搴旇鍦?绉掑悗杈撳嚭涓変釜IamMyPromise銆俹k锛屾垜浠潵娴嬭瘯涓€涓嬶細鍙互鐪嬪埌鎴戜滑鐨勬帶鍒跺彴鍦?绉掑悗鍙緭鍑轰簡涓€娆yPromise銆傝繖閲屽彂鐢熶簡浠€涔堬紵馃4銆傚厛涓嶆€ョ潃鍒嗘瀽bug鍘熷洜锛屾垜浠竴姝ユ鍒嗘瀽浠g爜鐨勬墽琛岄『搴忋€傞鍏堜細鎵цMyPromise涓璭xecutor鍑芥暟鐨勪唬鐮併€傜劧鍚庝唬鐮佷細鎵ц鍒皊etTimout锛岀劧鍚庡皢resolve鏀惧叆瀹忎换鍔¢槦鍒楃瓑寰?绉掋€俹k锛屾帴涓嬫潵灏辨槸鎵ц涓嬮潰涓変釜杩炵画鐨則hen鏂规硶浜嗐€傛敞鎰忓叏鏂囩涓€涓噸鐐规槸next锛氶噸鐐规槸鎴戜滑涓変釜then鏄悓姝ヤ唬鐮侊紝鎵€浠ヤ竴瀹氳鎶婅繖涓悶娓呮銆備簡瑙d簡杩欎竴鐐癸紝鎴戜滑闇€瑕佺湅鐪婱yPromise绫讳腑鍙戠敓浜嗕粈涔堛€傜敱浜庢垜浠殑resolve杩樺湪浠诲姟闃熷垪涓帓闃燂紝鎵€浠ユ鏃?00%鐨勭姸鎬佽繕鏄袱绉掑唴鐨刾ending鐘舵€併€傚彲浠ヨ鎴戜滑鐨勯偅涓椂鍊欒繕瑕佺户缁€傝繖閲岄渶瑕佺湅涓€涓媡hen鏂规硶涓殑閫昏緫銆傜敱浜庢鏃舵垜浠殑state==='pending'锛屾墍浠ユ垜浠牴鏈笉闇€瑕佽€冭檻鍚庨潰鐨勯€昏緫锛屽彧闇€瑕佽€冭檻绗竴涓猧f璇彞涓殑浠g爜鍗冲彲銆傚叧閿槸杩欓噷鐨勮繖娈典唬鐮併€傜劧鍚庢垜鍦ㄨ繖閲屽畬鎴愮殑涓変釜鐩稿綋浜庝笁涓綔涓氥€傝繖鎰忓懗鐫€浠€涔堬紵涓嶆槑鐧斤紵娌″叧绯伙紝閫氳繃鎴戞帴涓嬫潵鐨勫啓娉曚綘涓€瀹氳兘鏄庣櫧鎴戠殑鎰忔€濄€備綘浠ヤ负鎺у埗鍙颁細鍒嗗埆缁欎綘鍋氫笁閬嶏紵鐞嗚В浜嗚繖涓緥瀛愶紝浣犲叾瀹炲氨鑳界悊瑙d负浠€涔堟垜浠殑result鍙細杈撳嚭鎴戜滑涓婃璋冪敤鐨則hen鏂规硶鐨勭粨鏋滀簡銆傚洜涓哄墠涓ゆ閮借绗笁娆¤鐩栦簡銆傝繖灏辨槸涓轰粈涔堟垜浠湅鍒颁笅闈㈢殑缁撴灉锛屽彧杈撳嚭浜嗕竴涓猺esult3銆?.瑙e喅bug鐜板湪濡備綍瑙e喅杩欎釜闂锛熸病閿欙紝鏁扮粍锛佹垜浠彧闇€瑕佸皢鍘熷鐨刢allBackFn浠庝竴涓畝鍗曠殑鍙橀噺杞崲涓轰竴涓暟缁勫嵆鍙€傛帴涓嬫潵锛岃鎴戜滑鏀归€犳垜浠殑then鏂规硶銆傜瓑绛夛紝鎴戣寰椾綘澶ф鐜囦細鍍忎笂闈㈣繖鏍峰啓銆傚叾瀹烇紝杩欐槸闈炲父閿欒鐨勩€傛偍鐨勯€昏緫鏄皢onFulfilled(this.$result)鍑芥暟鐨勭粨鏋滄帹閫佸埌鏁版嵁涓紝鑰屼笉鏄皢鍑芥暟鎺ㄩ€佸埌鏁扮粍涓€傛墍浠ユ纭殑鍐欐硶搴旇鏄垜浠敤绠ご鍑芥暟鍖呰9涓€灞傦紝濡備笅鍥俱€備笂闈唬鐮佺殑鎰忔€濇槸锛屽鏋滄垜鍦ㄤ繚瀛樺紓姝ユ暟鎹紝鍥犱负鐘舵€佷笉鑳界涓€鏃堕棿浠巔ending鐘舵€佹敼鍙橈紝閭d箞鎴戜細鍏坧ush涓€涓澶村嚱鏁板埌涓€涓彨callBackFnArray鐨勬暟缁勪腑銆傞偅涔堟垜浠暟鎹腑绉疮鐨勫洖璋冨嚱鏁板幓鍝噷鎵ц鍛紵杩欓噷鎴戜滑闇€瑕佷慨鏀规垜浠殑resolve鍑芥暟銆傛垜浠渶瑕佸皢涓婇潰鐨勬棫浠g爜杞崲鎴愪笅闈㈢殑浠g爜銆傛垜浠湪鏁扮粍涓婁娇鐢╢orEach鏉ヨ幏鍙栨瘡涓€涓澶村嚱鏁帮紝鐒跺悗渚濇璋冪敤瀹冧滑銆俹k锛屾垜浠潵娴嬭瘯涓€涓嬭繖涓緥瀛愶紝鐪嬬湅鎴戜滑鐨勬€濊矾鏄惁姝g‘銆備笅闈㈡槸鎺у埗鍙拌緭鍑恒€傛槸鐨勶紝鎴戜滑鎴愬姛鍦拌В鍐充簡杩欎釜妫樻墜鐨勯棶棰樸€?.then鍑芥暟涔嬫墍浠ュ彲浠ラ摼寮忚皟鐢ㄦ垜浠煡閬撳師鐢烶romise鏈€澶х殑鐗圭偣灏辨槸鍙互璁╂垜浠户缁璽hen銆傚涓嬨€傛垜浠笉鑳藉彧鐭ラ亾鍙互杩欐牱鐢紝杩樿娓呮涓轰粈涔堝彲浠ヨ繖鏍风敤銆傞鍏堟垜浠瑃hen鍑芥暟鐨勮皟鐢ㄨ€呮槸涓嶆槸涓€涓狿romise瀹炰緥锛熷鏋滅浜屼釜then鏂规硶鍙互璋冪敤锛屾槸涓嶆槸璇存槑杩欎覆浠g爜涔熸槸涓€涓狿romise馃锛熷浣曢獙璇侊紵寰堢畝鍗曪紝鎴戜滑鎵撳嵃瀹冪殑杩斿洖鍊间笉琛屽悧锛熺収鍔炲惂锛屾垜浠敤涓€涓彉閲弔est鎺ユ敹绗竴涓猼hen鏂规硶鐨勮繑鍥炲€紃esult锛岀湅鐪嬫槸浠€涔堛€傝鎴戜滑鐪嬬湅鎺у埗鍙般€傛灉鐒舵槸涓€涓狿romise鍒嗘瀽瀹屽師鏉ョ殑Promise锛屾垜浠啀鏉ュ垎鏋愪竴涓嬫垜浠殑MyPromise銆備笉骞哥殑鏄紝鎴戜滑鐨則hen杩斿洖undefined銆倁ndefined鏈塼hen鏂规硶鍚楋紵鏄剧劧涓嶆槸锛屽浣曡В鍐筹紵鎴戜滑寰€涓嬬湅銆傚埌鐩墠涓烘锛屾偍鐨勪唬鐮佸簲璇ュ涓嬫墍绀恒€備负浜嗘柟渚垮ぇ瀹惰繘琛屼笅涓€姝ワ紝鎴戠洿鎺ヨ创婧愮爜銆傚鏋滀綘閿欒繃浜嗕换浣曚竴姝ワ紝浣犲彲浠ユ牴鎹垜鐜板湪鐨勪唬鐮佸仛涓€浜涜皟鏁淬€傜被MyPromise{#result:浠讳綍;#state锛氣€滃緟瀹氣€潀鈥滄弧瓒斥€潀鈥滄嫆缁濃€?#callBackFnArray锛氶樀鍒?浠讳綍>锛涙瀯閫犲嚱鏁帮紙鎵ц鍣細鍑芥暟锛墈this.#callBackFnArray=[];this.#state="pending";鎵ц鑰咃紙this.resolve.bind锛坱his锛夛紝this.reject.bind锛坱his锛夛級锛泒resolve(value){if(this.#state!=="pending")杩斿洖锛涜繖涓€?result=鍊硷紱this.#state="fulfilled";if(this.#callBackFnArray.length>0){queueMicrotask(()=>{this.#callBackFnArray.forEach((onFulfilled)=>{onFulfilled();});});}else{杩斿洖锛泒}reject(value){if(this.#state!=="pending")杩斿洖锛涜繖涓€?result=鍊硷紱this.#state="鎷掔粷";}then(onFulfilled,onRejected){if(this.#state==="pending"){this.#callBackFnArray.push(()=>{onFulfilled(this.#result);});}elseif(this.#state==="fulfilled"){queueMicrotask(()=>{onFulfilled(this.#result);});}elseif(this.#state==="rejected"){onRejected(this.#result);}}}鍏€傚疄鐜皌hen鍑芥暟鐨勯摼寮忚皟鐢ㄦ棦鐒舵垜浠煡閬撹瀹炵幇then鏂规硶鐨勯摼寮忚皟鐢紝閭d箞then鏂规硶鏈韩鐨勮繑鍥炲€间篃闇€瑕佹槸涓€涓狿romiseExample閭d箞浣犲湪鎯充粈涔堬紝鎴戜滑鐩存帴鐪嬬粨鏋勭殑then鍔熻兘銆傛垜浠洿鎺ヨ繑鍥炰竴涓柊鐨凪yPromise瀹炰緥锛岀劧鍚庡氨鏄渶鍏抽敭鐨勪竴鐐癸紝鎴戜滑涔嬪墠涓€鐩村湪寮鸿皟锛屽ぇ瀹朵竴瀹氳璁颁綇锛丮yPromise鐨勫弬鏁癳xecutor鏄竴涓櫘閫氱殑鍑芥暟锛屼細绔嬪嵆鎵ц銆傛棦鐒朵細绔嬪嵆鎵ц锛岄偅涔堟垜浠妸then鍑芥暟閲岄潰鐨勯€昏緫浠g爜鏀惧湪閲岄潰鏈夋病鏈夋晥鏋滃憿锛熸搷浣滈潪甯哥畝鍗曪紝灏嗗墠闈㈢殑浠g爜澶嶅埗绮樿创鍒版垜浠殑鎵ц鍣ㄥ嚱鏁颁腑鍗冲彲銆?/br>缁撴灉濡備笅锛氳繖鍙槸绗竴姝ワ紝鐪嬭繃鎴戜箣鍓嶅垎鏋愮殑璇昏€呴兘鐭ラ亾-銆婃墜鍐欌€滃洖璋冨湴鐙扁€濄€嬨€傛垜浠琻extthen鏂规硶璇诲彇鐨勭粨鏋滃氨鏄箣鍓嶇殑onFulfilled鎴栬€卭nRejected鐨勮繑鍥炲€笺€傞偅涔堟垜浠繖閲屾€庝箞璇诲憿锛熸敞鎰忔垜涓婇潰涓ゆ浠g爜鐨勬剰鎬濄€傝繖涓嚱鏁扮殑鎵ц缁撴灉浠h〃鐨勬槸onFulfilled鍑芥暟鐨勮繑鍥炲€煎悧锛熷綋涓嬮潰涓や釜绠ご鍑芥暟鎵ц鏃讹紝onFulfilled(this.#result)鐨勭粨鏋滀細浠ュ洖璋冨嚱鏁扮殑褰㈠紡浼犻€掔粰鎴戜滑銆傝繖纭疄鏄竴涓毦鐐癸紝闇€瑕佽鑰呮繁鍏ョ悊瑙d笅涓€涓猺esolve浣滀负鍥炶皟鍑芥暟鐨勬剰涔夛紝鎵嶈兘淇濆瓨鏁版嵁銆傛渶鍚庢垜浠祴璇曢摼寮忚皟鐢ㄦ槸鍚﹀彲浠ユ甯搞€傜粡杩囧崈杈涗竾鑻︼紝鎴戜滑缁堜簬瀹屾垚浜唗hen鐨勯摼寮忚皟鐢?.婧愮爜杩欓噷璐村嚭鎴戜滑鏈€缁堝疄鐜扮殑MyPromise鐨勬簮鐮併€傜被MyPromise{#result:浠讳綍;#state锛氣€滃緟瀹氣€潀鈥滄弧瓒斥€潀鈥滄嫆缁濃€?#callBackFnArray锛氶樀鍒?浠讳綍>锛涙瀯閫犲嚱鏁帮紙鎵ц鍣細鍑芥暟锛墈this.#callBackFnArray=[];this.#state="pending";鎵ц鑰咃紙this.resolve.bind锛坱his锛夛紝this.reject.bind锛坱his锛夛級锛泒resolve(value){if(this.#state!=="pending")杩斿洖锛涜繖涓€?result=鍊硷紱this.#state="fulfilled";if(this.#callBackFnArray.length>0){queueMicrotask(()=>{this.#callBackFnArray.forEach((onFulfilled)=>{onFulfilled();});});}else{杩斿洖锛泒}reject(value){if(this.#state!=="pending")杩斿洖锛涜繖涓€?result=鍊硷紱this.#state="鎷掔粷";}then(onFulfilled,onRejected?){returnnewMyPromise((resolve,reject)=>{if(this.#state==="pending"){this.#callBackFnArray.push(()=>{resolve(onFulfilled(this.#result));});}elseif(this.#state==="fulfilled"){queueMicrotask(()=>{resolve(onFulfilled(this.#result));});}elseif(this.#state==="rejected"){onRejected(this.#result);}});}}鍏€傜粨璇叾瀹炲湪鎴戠殑涓撴爮銆妀s杩涢樁涔嬭矾銆嬮噷锛屼粠绗竴绡囧紑濮嬪氨娣卞彈鎰熷姩銆備笉鐭ラ亾鑷繁鐨勪竴鐐圭偣鐭ヨ瘑鑳戒笉鑳芥弧瓒崇幇鍦ㄥ揩鑺傚鐨勯槄璇讳範鎯€傘€傘€傚彧鑳界珯鍦ㄥ叏鏄柊鎵嬬殑瑙備紬鐨勮搴︼紝绔欏湪浣滆€呯殑瑙掑害鑰冭檻姣忎竴涓棶棰橈紝鍖呮嫭涔嬪墠鐨勬枃绔狅紝鎴戞槸浠庤嚜宸辩殑鍗氬涓€愭笎浣撲細鍒扮殑銆傜悊瑙d粬浠兂瑕佽〃杈剧殑鐭ヨ瘑鐐瑰苟涓嶅鏄擄紝涔熷緢闅撅紝浣嗕篃姝f槸鍥犱负鏈変簡浠栦滑锛屾垜浠墠鑳介伩鍏嶈俯鍒版洿澶氱殑闄烽槺銆傛垜涔熸槸灏忕櫧鍑鸿韩锛屼篃娣辩煡瀛︿範鐨勪笉鏄撱€傚鏋滄偍瑙夊緱鏈枃瀵规偍鏈夋墍甯姪锛屽笇鏈涘垎浜粰瀛︿範鏃呴€斾腑鐨勬湅鍙嬨€傚彧鍥犺闆ㄦ穻婀夸簡锛屾兂涓鸿繜鍒扮殑浜烘拺浼炩様锔忥綖鍦ㄨ繖閲屼篃鎭枩鑷繁锛屻€婃墜鍐橮romise銆嬪畬缁撹姳馃帀