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

前端内训基础——深入理解浏览器的Event-loop

时间:2023-04-05 10:49:57 HTML5

鑳屾櫙Eventloop鏄竴涓緢閲嶈鐨勬蹇碉紝鏈川涓婃寚鐨勬槸璁$畻鏈虹殑杩愯鏈哄埗锛屼篃灏辨槸JavaScript璇█浣跨敤鐨勬満鍒躲€備紬鎵€鍛ㄧ煡锛孞avaScript鏄崟绾跨▼鐨勶紝涓轰粈涔堣璁捐鎴愬崟绾跨▼鍛紵鍏跺疄鏃╁湪鍑犲勾鍓嶏紝闃竴宄拌€佸笀灏辩粰鍑轰簡绛旀锛岃繖鏍风殑濂藉灏辨槸鎻愰珮鏁堢巼锛屼竴娆″彧鍋氫竴浠朵簨銆備絾鏄繖涔熷鑷翠簡涓€涓棶棰橈細灏辨槸鎵€鏈夌殑浠诲姟閮介渶瑕佹帓闃燂紝鍙湁鍓嶉潰鐨勪换鍔℃墽琛屽畬浜嗘墠鑳芥墽琛屽悗闈㈢殑浠诲姟銆侸avaScript璇█鐨勮璁¤€呮剰璇嗗埌杩欐槸涓嶅彲鑳界殑锛屾墍浠ヤ粬浠皢鎵€鏈夌殑浠诲姟鍒嗕负涓ょ锛氬悓姝ヤ换鍔″拰寮傛浠诲姟缁存姢涓€涓换鍔¢槦鍒楋紝涓荤嚎绋嬩粠浠诲姟闃熷垪涓鍙栦换鍔°€傛暣涓繃绋嬫槸寰幆鐨勩€傝繖绉嶆満鍒跺彨鍋欵ventloop锛屼篃鍙簨浠跺惊鐜€備负浠€涔堥渶瑕佸湪瀹為檯宸ヤ綔涓簡瑙e畠锛熶簡瑙d簨浠跺惊鐜彲浠ュ府鍔╂偍鍒嗘瀽寮傛搴忓垪闂銆傛澶栵紝瀵逛簬鐞嗚В娴忚鍣ㄥ拰Node.js鐨勫唴閮ㄦ満鍒朵篃鑳借捣鍒扮Н鏋佺殑浣滅敤銆傛渶閲嶈鐨勬槸闈㈣瘯銆傝繖鏄竴涓?00%浼氳闂埌鐨勯棶棰樸€傛祻瑙堝櫒瀹炵幇娴忚鍣ㄤ腑鐨勪富瑕佷换鍔″垎涓哄悓姝ヤ换鍔″拰寮傛浠诲姟涓ょ锛涘紓姝ヤ换鍔★細Macrotask锛堝畯浠诲姟锛夈€丮icrotask锛堝井浠诲姟锛夛紝macrotask鍜宮icrotask闃熷垪涓殑浠诲姟渚濇涓猴細鍏ユ爤銆佸嚭鏍堛€佷换鍔″嚭闃熴€佷氦鏇垮叆闃熴€備綘鍙互閫氳繃涓€涓吉浠g爜鏉ョ悊瑙h繖涓蹇碉細//taskqueue(firstin,firstout)letEventLoop=[];璁╀簨浠讹紱//鎵ц鈥滄案杩溾€漺hile(true){//atackif(EventLoop.length>0){//鑾峰彇闃熷垪涓殑涓嬩竴涓簨浠秂vent=EventLoop.shift();//鐜板湪锛屾墽琛屼笅涓€涓簨浠秨catch(error){//鎶ュ憡閿欒reportError(error);}}}甯哥敤Macrotask锛堝畯浠诲姟锛夎剼鏈爣绛緎etTimeoutsetIntervalsetImmediate锛圢ode鐜锛塺equestAnimationFrameMicrotask锛堝井浠诲姟锛塸rocess.nextTick锛圢ode鐜锛塒romise鍥炶皟鍖呮嫭锛?)MutationObserver浜嗚В浜嗘蹇典箣鍚庯紝鎴戜滑鍏堜粠涓€涓畝鍗曠殑渚嬪瓙寮€濮嬨€備綘涓嶉渶瑕佺煡閬撲笂娆℃墽琛岀殑鎵撳嵃缁撴灉锛屼綘搴旇鐭ラ亾褰撳墠浠g爜鏄畯浠诲姟锛屽井浠诲姟鏍楀瓙馃尠console.log('start');//number1setTimeout(function(){//number2console.log('timeout');},0);Promise.resolve().then(function(){//number3console.log('promise');});console.log('缁撴潫');//4鍙峰疄鐜扮殑娴佺▼锛氭祦绋嬶細杩愯鏃惰瘑鍒玪og鏂规硶骞跺叆鏍堬紝鐒跺悗杈撳叆start鍑烘爤銆係etTimeout琚瘑鍒负寮傛鏂规硶锛堝畯浠诲姟锛夛紝鍖垮悕鍥炶皟鍑芥暟鏀惧湪锛堝畯浠诲姟锛夐槦鍒椾腑銆傚湪涓嬩竴涓簨浠跺惊鐜腑鎵ц銆傚綋鎵ц閬囧埌promise鍥炶皟鏃讹紝灞炰簬(microtask)锛屾斁鍏?microtask)闃熷垪銆傝繍琛屾椂璇嗗埆鍒發og鏂规硶骞跺帇鏍堬紝鐒跺悗鎵ц杈撳叆绔皢鍏跺脊鍑烘爤銆備富杩涚▼鎵ц瀹屽悗鏍堜负绌猴紝鐒跺悗浠?microtask)闃熷垪涓彇鍑洪槦澶寸殑item锛屾墦鍗皃romise锛岀洿鍒?microtask)闃熷垪涓病鏈夋暟鎹€俷ext(macrotask)闃熷垪閬靛惊鍏堣繘鍏堝嚭鍘熷垯锛屾墦鍗拌秴鏃朵换鍔$殑绫诲瀷缂栧彿涓?锛氬悓姝ヤ换鍔$紪鍙?锛氬畯浠诲姟缂栧彿3锛氬井浠诲姟缂栧彿4锛氬悓姝ヤ换鍔℃墽琛岀粨鏋滐細startendpromisetimeoutstrikes褰撶啫鏂楀緢鐑苟鍑虹幇console.log('start');//Number1newPromise(function(resolve,rejected){console.log('Promise-1')//number2resolve()}).then(function(res){//number3console.log('Promise-2')})setTimeout(function(){//鏁板瓧4console.log('timeout');},0);Promise.resolve().then(function(){//鏁板瓧5console.log('鎵胯');});console.log('缁撴潫');//Number6瀹炵幇杩愯娴佺▼锛氬叾瀹炶繖涓緥瀛愬拰涓婇潰鐨勫敮涓€鍖哄埆灏辨槸澧炲姞浜嗕竴涓柊鐨凱romise锛屼篃灏辨槸number2闇€瑕佹墦鍗癱onsole.log('Promise-1')娉ㄦ剰鍙湁Promise鍥炶皟鏄竴涓紓姝ヤ换鍔★紙microtask锛夛紝浣嗘槸鍦ㄥ嚱鏁板唴閮ㄥ嵈鏄竴涓悓姝ヤ换鍔★紝杩欓噷寰堝浜虹粡甯告贩娣嗐€傜粨鏋滐細startPromise-1endPromise-2promisetimeout瀹屽叏瑙i攣浜嬩欢寰幆console.log('1');asyncfunctionfoo(){console.log('13');绛夊緟閰掑惂锛堬級锛沜onsole.log('15');}functionbar(){console.log('14');}setTimeout(function(){console.log('2');newPromise(function(resolve){鎺у埗鍙般€俵og('4');resolve();}).then(function(){console.log('5');});});newPromise(function(resolve){console.log('7');resolve();}).then(function(){console.log('8');});setTimeout(function(){console.log('9');newPromise(function(resolve){console.log('11');resolve();}).then(function(){console.log('12');});});foo();瀹炵幇杩愯杩囩▼锛氱涓€涓簨浠跺惊鐜細鍦ㄥ畯浠诲姟涓В鏋愭暣涓狫avaScript鏂囦欢锛岄亣鍒板悓姝onsole.log('1')锛岀洿鎺ユ墦鍗般€傜劧鍚庢墽琛岄亣鍒颁竴涓嚱鏁颁絾鏄病鏈夎皟鐢ㄧ洿鎺ヨ烦杩囷紝鏉ュ埌绗竴涓猻etTimeout锛屽杩涙爣璁颁负macro1鐨勶紙瀹忎换鍔★級Queue锛岀劧鍚庤В鏋愬埌鏂扮殑Promise鎵ц浠g爜console.log('7'),閬囧埌鐒跺悗濉炶繘(寰换鍔?Queue鏍囪涓簃icro1,鐒跺悗閬囧埌setTimeout鍐嶆濉炶繘(瀹忎换鍔?Queue鏍囪涓簃acro2,鏈€鍚庡埌foo()鍑芥暟,鍙橀噺鎻愬崌鎵цfoo鍑芥暟閬囧埌async鍙槸璇存槑褰撳墠鍑芥暟鏄紓姝ョ殑锛屼笉褰卞搷鍑芥暟console.log('13')鐨勬墽琛岋紝閬囧埌awiatbar鏃讹紝鎵цbar鐨刢onsole.log('14')锛宎wiat鍜屽潡鍚庨潰鐨勪唬鐮侊紝鎶婂畠鏀惧埌microtask鍒楄〃涓爣璁颁负micro2锛涘綋鍓嶅畯浠诲姟锛氭墽琛岀殑鍚屾浠g爜涓猴細[1,7,13,14]寰换鍔¢槦鍒楋細[8,15]瀹忎换鍔¢槦鍒楋細[macro1,macro2]姝ゆ椂杈撳叆缁撴灉锛?,7,13,14,8,15杈撳叆瀹屾垚鍚庯紝娓呯┖褰撳墠寰换鍔¢槦鍒椼€傛鏃讹紝micro=[]绗簩涓簨浠跺惊鐜細淇濇寔鍏堣繘鍏堝嚭鐨勫舰寮忥紝鎵ц绗竴涓猻etTimeout杈撳嚭console.log('2')锛屾墽琛屽埌鏂扮殑promise杈撳叆鍒癱onsole.log('4')锛屾斁鍦╩icro涓紝閬囧埌then鏃舵爣璁颁负micro1锛屾病鏈夊叾浠杕icrotask鏃剁洿鎺ヨ緭鍑篶onsole.log('5')銆傚綋鍓嶅畯浠诲姟锛欵xecute鍚屾鐮佷负锛歔2,4]寰换鍔¢槦鍒楋細[5]瀹忎换鍔¢槦鍒楋細[macro2]姝ゆ椂杈撳叆鐨勭粨鏋滐細2,4,5褰撳墠寰换鍔¢槦鍒楁鏃舵竻闆秏icro=[]涓変釜浜嬩欢寰幆锛氫笌涓婁竴涓簨浠跺惊鐜『搴忕浉鍚屽綋鍓嶅畯浠诲姟锛氭墽琛岀殑鍚屾浠g爜涓猴細[9,11]寰换鍔¢槦鍒楋細[12]瀹忎换鍔¢槦鍒楋細[]鐨勬鏃惰緭鍏ョ粨鏋滐細9銆?112銆佽緭鍏ュ悗娓呯┖鎵€鏈変换鍔¢槦鍒椼€傛€荤粨鍦ㄤ簨浠跺惊鐜腑鍖哄垎瀹忎换鍔″拰寰换鍔¢潪甯搁噸瑕併€傚彧鏈夋妸椤哄簭寮勬竻妤氫簡锛屾墠鑳界煡閬撳綋鍓嶄簨浠舵墽琛岀殑鍏堝悗椤哄簭锛屽湪闈㈣瘯鍜屽悗闈㈢殑宸ヤ綔涓兘浼氬緢杞绘澗銆?/p>