浣犱笉鐭ラ亾鐨?Event Loop
Posted 鍥鹃泙绀惧尯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浣犱笉鐭ラ亾鐨?Event Loop相关的知识,希望对你有一定的参考价值。
鏈枃鐢卞浘闆€绀惧尯璁よ瘉浣滆€?Horace 鍐欎綔鑰屾垚锛岀偣鍑婚槄璇诲師鏂囨煡鐪嬩綔鑰呮帢閲戦摼鎺ワ紝鍦ㄦ枃绔犲熬閮ㄦ煡鐪嬩綔鑰呯殑鍗氬閾炬帴[1]锛屾劅璋綔鑰呯殑浼樿川杈撳嚭锛岃鎴戜滑鐨勬妧鏈笘鐣屽彉寰楁洿鍔犵編濂金煒?/p>
绗旇€呮渶杩戝繖鐫€鍋氶」鐩箣绫荤殑锛屾枃绔犺緭鍑洪仐钀戒笅浜嗕竴娈垫椂闂达紝杩欐鎴戜滑灏辨潵鑱婁竴涓潰璇曚腑涓€涓瘮杈冮噸瑕佺殑鐭ヨ瘑鐐?鈥斺€?Event Loop
鍙兘鏈変汉浼氬鎬竴涓?EventLoop 杩樿兘鍐欏嚭浠€涔堬紝涓斿惉鎴戞參鎱㈡潵閫煎彣锛岀湅瀹岃繖绡囨枃绔犲甫浣犳悶瀹?Event Loop 浠ュ強瀹冪浉鍏崇殑涓€浜涚煡璇嗙偣銆?/p>
涓€銆丒vent Loop 鏄粈涔?/h1>
鍦ㄥ紑濮嬭 Event Loop 涔嬪墠锛屾垜浠厛鏉ヨ璇嗕竴涓嬪畠鍒板簳鏄釜浠€涔堜笢瑗裤€?/p>
In computer science, the event loop is a programming construct or design pattern that waits for and dispatches events or messages in a program. The event loop works by making a request to some internal or external "event provider" (that generally blocks the request until an event has arrived), then calls the relevant event handler ("dispatches the event"). The event loop is also sometimes referred to as the message dispatcher, message loop, message pump, or run loop.
涓婇潰杩欐鏄?span class="mq-17">Wikipedia[2]瀵?Event Loop 鐨勮В閲婏紝绠€鍗曠殑鏉ヨ灏辨槸Event Loop鏄竴涓▼搴忕粨鏋勶紝鐢ㄤ簬绛夊緟鍜屽垎娲炬秷鎭拰浜嬩欢
鎴戜釜浜虹殑鐞嗚В鏄?JS 涓殑 Event Loop 鏄祻瑙堝櫒鎴?Node 鐨勪竴绉嶅崗璋?JavaScript 鍗曠嚎绋嬭繍琛屾椂涓嶄細闃诲鐨勪竴绉嶆満鍒躲€?/p>
涓轰粈涔堣瀛?Event Loop锛?/h2>
鍙兘鏈変汉浼氭瘮杈冪枒鎯戝墠绔负浠€涔堣瀛︾湅璧锋潵姣旇緝搴曞眰鐨?Event Loop锛屼笉浠呬粎鏄洜涓鸿繖鏄竴閬撻潰璇曠殑甯歌€冮銆?/p>
-
浣滀负涓€涓▼搴忓憳锛屼簡瑙g▼搴忕殑杩愯鏈哄埗鏄緢閲嶈鐨勶紝杩欐牱鍙互甯姪浣犲幓杈撳嚭鏇翠紭璐ㄧ殑浠g爜銆? -
鍓嶇鏄竴涓寖鍥村緢骞跨殑棰嗗煙锛屾妧鏈竴鐩村湪鏇存柊杩唬锛屾帉鎻′簡搴曞眰鐨勫師鐞嗗彲浠ュ簲瀵规柊鐨勬妧鏈€? -
涓€涓紭绉€鐨勭▼搴忓憳瑕佽兘璁╁啓鐨勪唬鐮佹寜鐓ц嚜宸辨兂鐨勫幓杩愯锛屽鏋滆繛浠g爜鏈韩鐨勮繍琛屾満鍒堕兘鏃犳硶鎺屾彙鐨勮瘽锛屽氨涓嶇敤璋堜粈涔堟帉鎺ц嚜宸辩殑浠g爜浜嗐€?
浜屻€佽繘绋嬪拰绾跨▼
涓婃枃鎴戣浜?Event Loop 鏄崟绾跨▼闃诲闂鐨勪竴绉嶈В鍐虫満鍒讹紝鎵€浠ュ湪姝e紡寮€濮嬪墠杩樻槸瑕佸厛浠庤繘绋嬪拰绾跨▼鐨勮搴︽潵鑱婁竴鑱娿€備紬鎵€鍛ㄧ煡鐨勪竴浠朵簨鏄紝JavaScript 鏄竴涓崟绾跨▼鏈哄埗鐨勮瑷€锛岄偅鎴戜滑鍏堟潵鐪嬬湅杩涚▼鍜岀嚎绋嬬殑瀹氫箟锛?/p>
瀹氫箟
-
杩涚▼锛氳繘绋嬫槸 CPU 璧勬簮鍒嗛厤鐨勬渶灏忓崟浣? -
绾跨▼锛氱嚎绋嬫槸 CPU 璋冨害鐨勬渶灏忓崟浣?
鏇撮€氫織鐨勬潵璇达紝杩涚▼灏卞儚鏄竴瀹跺伐鍘傦紝澶氫釜宸ュ巶涔嬮棿鏄嫭绔嬪瓨鍦ㄧ殑銆傝€岀嚎绋嬪氨鍍忔槸宸ュ巶涓殑閭d簺宸ヤ汉锛屽叡浜祫婧愶紝瀹屾垚鍚屼竴涓ぇ鐩爣銆?/p>
JS 鐨勫崟绾跨▼
寰堝浜洪兘鐭ラ亾鐨勬槸锛孞avaScript 鏄竴闂?span class="mq-39">鍔ㄦ€佺殑瑙i噴鍨嬬殑璇█锛屽叿鏈?span class="mq-40">璺ㄥ钩鍙版€?/strong>銆傚湪琚棶鍒?JavaScript 涓轰粈涔堟槸涓€闂ㄥ崟绾跨▼鐨勮瑷€锛屾湁鐨勪汉鍙兘浼氳繖涔堝洖绛旓細鈥滆瑷€鐗规€у喅瀹氫簡 JavaScript 鏄竴涓崟绾跨▼璇█锛孞avaScript 澶╃敓鏄竴涓崟绾跨▼璇█鈥濓紝杩欏彧涓嶈繃鏄竴灞傜硸琛g舰浜嗐€?/p>
JavaScript 浠庤癁鐢熻捣灏辨槸鍗曠嚎绋嬶紝鍘熷洜澶ф鏄笉鎯宠娴忚鍣ㄥ彉寰楀お澶嶆潅锛屽洜涓哄绾跨▼闇€瑕佸叡浜祫婧愩€佷笖鏈夊彲鑳戒慨鏀瑰郊姝ょ殑杩愯缁撴灉锛屽浜庝竴绉嶇綉椤佃剼鏈瑷€鏉ヨ锛岃繖灏卞お澶嶆潅浜嗐€?/p>
鍑嗙‘鐨勬潵璇达紝鎴戣涓?javascript 鐨勫崟绾跨▼鏄寚 JavaScript 寮曟搸鏄崟绾跨▼鐨勶紝JavaScript 鐨勫紩鎿庡苟涓嶆槸鐙珛杩愯鐨勶紝璺ㄥ钩鍙版剰鍛崇潃 JavaScript 渚濊禆鍏惰繍琛岀殑瀹夸富鐜 --- 娴忚鍣?澶ч儴鍒嗘儏鍐典笅鏄祻瑙堝櫒)銆?/p>
娴忚鍣ㄩ渶瑕佹覆鏌?DOM锛孞avaScript 鍙互淇敼 DOM 缁撴瀯锛孞avaScript 鎵ц鏃讹紝娴忚鍣?DOM 娓叉煋鍋滄銆傚鏋?JavaScript 寮曟搸绾跨▼涓嶆槸鍗曠嚎绋嬬殑锛岄偅涔堝彲浠ュ悓鏃舵墽琛屽娈?JavaScript锛屽鏋滆繖澶氭 JavaScript 閮芥搷浣?DOM锛岄偅涔堝氨浼氬嚭鐜?DOM 鍐茬獊銆?/p>
涓句釜渚嬪瓙鏉ヨ锛屽湪鍚屼竴鏃跺埢鎵ц涓や釜 script 瀵瑰悓涓€涓?DOM 鍏冪礌杩涜鎿嶄綔锛屼竴涓慨鏀?DOM锛屼竴涓垹闄?DOM锛岄偅杩欐牱璇濇祻瑙堝櫒灏变細鎳甸€间簡锛屽畠灏变笉鐭ラ亾鍒板簳璇ュ惉璋佺殑锛屼細鏈夎祫婧愮珵浜夛紝杩欎篃鏄?JavaScript 鍗曠嚎绋嬬殑鍘熷洜涔嬩竴銆?/p>
涔嬪墠璇磋繃锛孞avaScript 杩愯鐨勫涓荤幆澧冩祻瑙堝櫒鏄绾跨▼鐨勩€?/p>
浠?Chrome 鏉ヨ锛屾垜浠彲浠ラ€氳繃 Chrome 鐨勪换鍔$鐞嗗櫒鏉ョ湅鐪嬨€?/p>
褰撲綘鎵撳紑涓€涓?Tab 椤甸潰鐨勬椂鍊欙紝灏卞垱寤轰簡涓€涓繘绋嬨€傚鏋滀粠涓€涓〉闈㈡墦寮€浜嗗彟涓€涓〉闈紝鎵撳紑鐨勯〉闈㈠拰褰撳墠鐨勯〉闈㈠睘浜庡悓涓€绔欑偣鐨勮瘽锛岄偅涔堣繖涓〉闈細澶嶇敤鐖堕〉闈㈢殑娓叉煋杩涚▼銆?/p>
杩欓噷娌$湅鎳傛病鍏崇郴锛屽悗闈㈡垜浼氬啀璇淬€?/p>
鐪嬪埌杩欓噷锛屾€荤畻鏄繘鍏ユ棰樹簡锛屽厛璁茶娴忚鍣ㄧ鐨?Event Loop 鏄粈涔堟牱鐨勩€?/p>
涓婂浘鏄竴寮?JS 鐨勮繍琛屾満鍒跺浘锛孞s 杩愯鏃跺ぇ鑷翠細鍒嗕负鍑犱釜閮ㄥ垎锛?/p>
璇村埌杩欓噷锛孍vent Loop 涔熷彲浠ョ悊瑙d负锛氫笉鏂湴浠庝换鍔¢槦鍒椾腑鍙栧嚭浠诲姟鎵ц鐨勪竴涓繃绋嬨€?/p>
涓婃枃宸茬粡璇磋繃浜?JavaScript 鏄竴闂ㄥ崟绾跨▼鐨勮瑷€锛屼竴娆″彧鑳芥墽琛屼竴涓换鍔★紝濡傛灉鎵€鏈夌殑浠诲姟閮芥槸鍚屾浠诲姟锛岄偅涔堢▼搴忓彲鑳藉洜涓虹瓑寰呬細鍑虹幇鍋囨鐘舵€侊紝杩欏浜庝竴涓敤鎴蜂綋楠屽緢寮虹殑璇█鏉ヨ鏄潪甯镐笉鍙嬪ソ鐨勩€?/p>
绠€鍗曠殑浠嬬粛涓€涓嬪悓姝ヤ换鍔″拰寮傛浠诲姟鐨勬蹇点€?/p>
浠庢蹇靛氨鍙互鐪嬪嚭鏉ワ紝寮傛浠诲姟浠庝竴瀹氱▼搴︿笂鏉ョ湅姣斿悓姝ヤ换鍔℃洿楂樻晥涓€浜涳紝鏍稿績鏄彁楂樹簡鐢ㄦ埛浣撻獙銆?/p>
Event Loop 寰堝ソ鐨勮皟搴︿簡浠诲姟鐨勮繍琛岋紝瀹忎换鍔″拰寰换鍔′篃鐭ラ亾浜嗭紝鐜板湪鎴戜滑灏辨潵鐪嬬湅瀹冪殑璋冨害杩愯鏈哄埗銆?/p>
JavaScript 鐨勪唬鐮佹墽琛屾椂锛屼富绾跨▼浼氫粠涓婂埌涓嬩竴姝ユ鐨勬墽琛屼唬鐮侊紝鍚屾浠诲姟浼氳渚濇鍔犲叆鎵ц鏍堜腑鍏堟墽琛岋紝寮傛浠诲姟浼氬湪鎷垮埌缁撴灉鐨勬椂鍊欏皢娉ㄥ唽鐨勫洖璋冨嚱鏁版斁鍏ヤ换鍔¢槦鍒楋紝褰撴墽琛屾爤涓殑娌℃湁浠诲姟鍦ㄦ墽琛岀殑鏃跺€欙紝寮曟搸浼氫粠浠诲姟闃熷垪涓鍙栦换鍔″帇鍏ユ墽琛屾爤(Call Stack)涓鐞嗘墽琛屻€?/p>
涓夈€佹祻瑙堝櫒
娴忚鍣ㄧ殑澶氱嚎绋?/h2>
娴忚鍣ㄤ富绾跨▼甯搁┗绾跨▼
鍥涖€佹祻瑙堝櫒绔殑 Event Loop
鍚屾浠诲姟鍜屽紓姝ヤ换鍔?/h2>
姒傚康
Event Loop
瀹忎换鍔″拰寰换鍔?span class="mq-110">
鐜板湪灏辨湁涓€涓棶棰樹簡锛屼换鍔¢槦鍒楁槸涓€涓秷鎭槦鍒楋紝鍏堣繘鍏堝嚭锛岄偅灏辨槸璇达紝鍚庢潵鐨勪簨浠堕兘鏄鍔犲湪闃熷熬绛夊埌鍓嶉潰鐨勪簨浠舵墽琛屽畬浜嗘墠浼氳鎵ц銆傚鏋滃湪鎵ц鐨勮繃绋嬩腑绐佺劧鏈夐噸瑕佺殑鏁版嵁闇€瑕佽幏鍙栵紝鎴栨槸璇存湁浜嬩欢绐佺劧闇€瑕佸鐞嗕竴涓嬶紝鎸夌収闃熷垪鐨勫厛杩涘厛鍑洪『搴忚繖浜涙槸鏃犳硶寰楀埌鍙婃椂澶勭悊鐨勩€傝繖涓椂鍊欏氨鍌敓浜嗗畯浠诲姟鍜屽井浠诲姟锛屽井浠诲姟浣垮緱涓€浜涘紓姝ヤ换鍔″緱鍒板強鏃剁殑澶勭悊銆?/p>
鏇剧粡鐪嬪埌鐨勪竴涓緥瀛愬緢濂斤紝瀹忎换鍔″拰寰换鍔″舰璞$殑鏉ヨ灏辨槸锛氫綘鍘昏惀涓氬巺鍔炰竴涓笟鍔′細鏈変竴涓帓闃熷彿鐮侊紝褰撳彨鍒颁綘鐨勫彿鐮佺殑鏃跺€欎綘鍘荤獥鍙e姙鍏呭€间笟鍔?瀹忎换鍔℃墽琛?锛屽湪浣犲姙鐞嗗厖鍊肩殑鏃跺€欎綘鍙堟兂鏀逛釜濂楅(寰换鍔?锛岃繖涓椂鍊欏伐浣滀汉鍛樹細鐩存帴甯綘鍔烇紝涓嶅彲鑳借浣犻噸鏂版帓闃熴€?/p>
鎵€浠ヤ笂鏂囪杩囩殑寮傛浠诲姟鍙堝垎涓哄畯浠诲姟鍜屽井浠诲姟锛孞S 杩愯鏃朵换鍔¢槦鍒椾細鍒嗕负瀹忎换鍔¢槦鍒楀拰寰换鍔¢槦鍒楋紝鍒嗗埆瀵瑰簲瀹忎换鍔″拰寰换鍔°€?/p>
鍏堜粙缁嶄竴涓?娴忚鍣ㄧ幆澧冪殑)瀹忎换鍔″拰寰换鍔″ぇ鑷存湁鍝簺锛?/p>
-
瀹忎换鍔★細 -
script(鏁翠綋鐨勪唬鐮? -
setTimeout -
setInterval -
I/O 鎿嶄綔 -
UI 娓叉煋 (瀵硅繖涓瑪鑰呮寔淇濈暀鎰忚) -
寰换鍔★細 -
Promise.then -
MutationObserver
浜嬩欢杩愯椤哄簭
-
鎵ц鍚屾浠诲姟锛屽悓姝ヤ换鍔′笉闇€瑕佸仛鐗规畩澶勭悊锛岀洿鎺ユ墽琛?涓嬮潰鐨勬楠や腑閬囧埌鍚屾浠诲姟閮芥槸涓€鏍峰鐞? --- 绗竴杞粠 script寮€濮? -
浠庡畯浠诲姟闃熷垪涓彇鍑洪槦澶翠换鍔℃墽琛? -
濡傛灉浜х敓浜嗗畯浠诲姟锛屽皢瀹忎换鍔℃斁鍏ュ畯浠诲姟闃熷垪锛屼笅娆¤疆寰殑鏃跺€欐墽琛? -
濡傛灉浜х敓浜嗗井浠诲姟锛屽皢寰换鍔℃斁鍏ュ井浠诲姟闃熷垪 -
鎵ц瀹屽綋鍓嶅畯浠诲姟涔嬪悗锛屽彇鍑哄井浠诲姟闃熷垪涓殑鎵€鏈変换鍔′緷娆℃墽琛? -
濡傛灉寰换鍔℃墽琛岃繃绋嬩腑浜х敓浜嗘柊鐨勫井浠诲姟锛屽垯缁х画鎵ц寰换鍔★紝鐩村埌寰换鍔$殑闃熷垪涓虹┖ -
杞惊锛屽惊鐜互涓?2 - 6
鎬荤殑鏉ヨ灏辨槸锛氬悓姝ヤ换鍔?瀹忎换鍔?-> 鎵ц浜х敓鐨勬墍鏈夊井浠诲姟(鍖呮嫭寰换鍔′骇鐢熺殑寰换鍔? -> 鍚屾浠诲姟/瀹忎换鍔?-> 鎵ц浜х敓鐨勬墍鏈夊井浠诲姟(鍖呮嫭寰换鍔′骇鐢熺殑寰换鍔? -> 寰幆......
娉ㄦ剰锛氬井浠诲姟闃熷垪
涓句釜鏍楀瓙
鍏夎涓嶇粌鍋囨妸寮忥紝鐜板湪灏辨潵鐪嬩竴涓緥瀛愶細
鏀惧浘鐨勫師鍥犳槸涓轰簡璁╁ぇ瀹跺湪鐪嬭В鏋愪箣鍓嶅彲浠ュ厛鑷繁鎸夌収杩愯椤哄簭璧颁竴閬嶏紝鍐欏ソ绛旀涔嬪悗鍐嶆潵鐪嬭В鏋愩€?br>瑙f瀽锛?br>(鐢ㄧ豢鑹茬殑琛ㄧず鍚屾浠诲姟鍜屽畯浠诲姟锛岀孩鑹茶〃绀哄井浠诲姟)
+ console.log('script start')
+ setTimeout(function() {
+ console.log('setTimeout')
+ }, 0)
+ new Promise((resolve, reject)=>{
+ console.log("promise1")
+ resolve()
+ })
- .then(()=>{
- console.log("then11")
+ new Promise((resolve, reject)=>{
+ console.log("promise2")
+ resolve();
+ })
- .then(() => {
- console.log("then2-1")
- })
- .then(() => {
- console.log("then2-2")
- })
- })
- .then(()=>{
- console.log("then12")
- })
+ console.log('script end')
-
棣栧厛閬囧埌 console.log()锛岃緭鍑? script start
-
閬囧埌 setTimeout 浜х敓瀹忎换鍔★紝娉ㄥ唽鍒? 瀹忎换鍔¢槦鍒梉setTimeout]锛屼笅涓€杞?Event Loop 鐨勬椂鍊欏湪鎵ц -
鐒跺悗閬囧埌 new Promise 鏋勯€犲0鏄?鍚屾)锛宭og 杈撳嚭 promise1
锛岀劧鍚?resolve -
resolve 鍖归厤鍒? promise1 鐨勭涓€涓?then锛屾妸杩欎釜 then 娉ㄥ唽鍒? 寰换鍔¢槦鍒梉then11]涓?/strong>锛岀户缁綋鍓嶆暣浣撹剼鏈殑鎵ц -
閬囧埌鏈€鍚庣殑涓€涓?log锛岃緭鍑? script end
锛? 褰撳墠鎵ц鏍堟竻绌?/strong> -
浠庡井浠诲姟闃熷垪涓彇鍑洪槦澶翠换鍔?then11' 杩涜鎵ц锛屽叾涓湁涓€涓?log锛岃緭鍑? then11
-
寰€涓嬮亣鍒?new Promise 鏋勯€犲0鏄?鍚屾)锛宭og 杈撳嚭 promise2
锛岀劧鍚?resolve -
resolve 鍖归厤鍒? promise2 鐨勭涓€涓?then锛屾妸杩欎釜 then 娉ㄥ唽鍒? 寰换鍔¢槦鍒梉then2-1]锛屽綋鍓?then11 鍙墽琛岄儴鍒嗙粨鏉燂紝鐒跺悗浜х敓浜? promise1 鐨勭浜屼釜 then锛屾妸杩欎釜 then 娉ㄥ唽鍒? 寰换鍔¢槦鍒梉then2-1, then12] -
鎷垮嚭寰换鍔¢槦澶翠换鍔?then2-1' 鎵ц锛宭og 杈撳嚭 then2-1
锛岃Е鍙? promise2 鐨勭浜屼釜 then锛屾敞鍐屽埌 寰换鍔¢槦鍒梉then12, then2-2] -
鎷垮嚭寰换鍔¢槦澶翠换鍔?then12'锛宭og 杈撳嚭 then12
-
鎷垮嚭寰换鍔¢槦澶翠换鍔?then2-2'锛宭og 杈撳嚭 then2-2
-
寰换鍔¢槦鍒楁墽琛屽畬姣曪紝鍒繕浜嗗畯浠诲姟闃熷垪涓殑 setTimeout锛宭og 杈撳嚭 setTimeout
缁忚繃浠ヤ笂涓€鐣紲(xia)瀵?gao)鍒嗘瀽锛屽笇鏈涙病鏈夌粫鏅曚綘锛屾渶鍚庣殑杈撳嚭缁撴灉灏辨槸锛?br>script start -> promise1 -> script end -> then11 -> promise2 -> then2-1 -> then12 -> then2-2 -> setTimeout
瀹忎换鍔★紵寰换鍔★紵
涓嶇煡閬撳ぇ瀹剁湅浜嗗畯浠诲姟鍜屽井浠诲姟涔嬪悗浼氫笉浼氭湁涓€涓枒鎯戯紝瀹忎换鍔″拰寰换鍔¢兘鏄紓姝ヤ换鍔★紝寰换鍔′箣鍓嶈杩囦簡鏄负浜嗗強鏃惰В鍐充竴浜涘繀瑕佷簨浠惰€屼骇鐢熺殑銆?/p>
-
涓轰粈涔堣鏈夊井浠诲姟锛?br>涓轰粈涔堣鏈夊井浠诲姟鐨勫師鍥犲墠闈㈠凡缁忚浜嗭紝杩欓噷灏变笉鍐嶈禈杩帮紝绠€鍗曡涓€涓嬪氨鏄负浜嗗強鏃跺鐞嗕竴浜涗换鍔★紝涓嶇劧绛夊埌鏈€鍚庡啀鎵ц鐨勬椂鍊欐嬁鍒扮殑鏁版嵁鍙兘宸茬粡鏄姹℃煋鐨勬暟鎹揪涓嶅埌棰勬湡鐩爣浜嗐€?/p>
-
鏄粈涔堝畯浠诲姟锛熶粈涔堟槸寰换鍔★紵
鐩镐俊澶у鍦ㄥ涔?Event Loop 鏌ユ壘璧勬枡鐨勬椂鍊欙紝鑲畾鍚勭璧勬枡閲岄潰閮戒細璁插埌瀹忎换鍔″拰寰换鍔★紝浣嗘槸涓嶇煡閬撲綘鏈夋病鏈夌伒榄傛嫹闂繃浣犺嚜宸憋細浠€涔堟槸瀹忎换鍔★紵浠€涔堟槸寰换鍔★紵鎬庝箞鍖哄垎瀹忎换鍔″拰寰换鍔★紵
涓嶈兘鍙槸榛樿鎺ュ彈杩欎釜姒傚康锛屽湪杩欓噷锛屾垜鏍规嵁鎴戠殑涓汉鐞嗚В杩涜涓€鐣(hu)鏄?che) -
瀹忎换鍔″拰寰换鍔$殑鐪熼潰鐩?br>鍏跺疄鍦?Chrome 鐨勬簮鐮佷腑骞舵病鏈変粈涔堝畯浠诲姟鍜屽井浠诲姟鐨勪唬鐮佹垨鏄鏄庯紝鍦?JS 澶т細[3]涓婃彁鍒拌繃寰换鍔¤繖涓悕璇嶏紝浣嗘槸涔熸病鏈夎鍒板簳浠€涔堟槸寰换鍔°€?/p>
瀹忎换鍔?br>鏂囩珷鏈€寮€濮嬬殑鏃跺€欒杩囷紝鍦?chrome 閲岋紝姣忎釜椤甸潰閮藉搴斾竴涓繘绋嬨€傝€岃杩涚▼鍙堟湁澶氫釜绾跨▼锛屾瘮濡?JS 绾跨▼銆佹覆鏌撶嚎绋嬨€両O 绾跨▼銆佺綉缁滅嚎绋嬨€佸畾鏃跺櫒绾跨▼绛夌瓑锛岃繖浜涚嚎绋嬩箣闂寸殑閫氫俊鏄€氳繃鍚戝璞$殑浠诲姟闃熷垪涓坊鍔犱竴涓换鍔★紙postTask锛夋潵瀹炵幇鐨勩€?span class="mq-228">瀹忎换鍔$殑鏈川鍙互璁や负鏄绾跨▼浜嬩欢寰幆鎴栨秷鎭惊鐜紝涔熷氨鏄嚎绋嬮棿閫氫俊鐨勪竴涓秷鎭槦鍒椼€?/strong>
灏辨嬁 setTimeout 涓句緥鏉ヨ锛屽綋閬囧埌瀹冪殑鏃跺€欙紝娴忚鍣ㄥ氨浼氬 Event Loop 璇达細鍢匡紝鎴戞湁涓€涓换鍔′氦缁欎綘锛孍vent Loop 灏变細璇达細濂界殑锛屾垜浼氭妸瀹冨姞鍒版垜鐨?todoList 涓紝涔嬪悗鎴戜細鎵ц瀹冿紝瀹冩槸闇€瑕佽皟鐢?API 鐨勩€?/p>
瀹忎换鍔$殑鐪熼潰鐩槸娴忚鍣ㄦ淳鍙戯紝涓?JS 寮曟搸鏃犲叧鐨勶紝鍙備笌浜?Event Loop 璋冨害鐨勪换鍔?/strong>
寰换鍔?br>寰换鍔℃槸鍦ㄨ繍琛屽畯浠诲姟/鍚屾浠诲姟鐨勬椂鍊欎骇鐢熺殑锛屾槸灞炰簬褰撳墠浠诲姟鐨勶紝鎵€浠ュ畠涓嶉渶瑕佹祻瑙堝櫒鐨勬敮鎸侊紝鍐呯疆鍦?JS 褰撲腑锛岀洿鎺ュ湪 JS 鐨勫紩鎿庝腑灏辫鎵ц鎺変簡銆?/p>
鐗规畩鐨勭偣
-
async 闅愬紡杩斿洖 Promise 浣滀负缁撴灉
-
鎵ц瀹?await 涔嬪悗鐩存帴璺冲嚭 async 鍑芥暟锛岃鍑烘墽琛岀殑鎵€鏈夋潈
-
褰撳墠浠诲姟鐨勫叾浠栦唬鐮佹墽琛屽畬涔嬪悗鍐嶆鑾峰緱鎵ц鏉冭繘琛屾墽琛?/p>
-
绔嬪嵆 resolve 鐨?Promise 瀵硅薄锛屾槸鍦ㄦ湰杞?浜嬩欢寰幆"鐨勭粨鏉熸椂鎵ц锛岃€屼笉鏄湪涓嬩竴杞?浜嬩欢寰幆"鐨勫紑濮嬫椂
鍐嶄妇涓牀瀛?span class="mq-247">
console.log('script start')
async function async1() {
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2 end')
}
async1()
setTimeout(function() {
console.log('setTimeout')
}, 0)
new Promise(resolve => {
console.log('Promise')
resolve()
})
.then(function() {
console.log('promise1')
})
.then(function() {
console.log('promise2')
})
console.log('script end')
鎸夌収涔嬪墠鐨勫垎鏋愭柟娉曞幓鍒嗘瀽涔嬪悗灏变細寰楀嚭涓€涓粨鏋滐細script start => async2 end => Promise => script end => promise1 => promise2 => async1 end => setTimeout
鍙互鐪嬪嚭 async1 鍑芥暟鑾峰彇鎵ц鏉冩槸浣滀负寰换鍔$殑闃熷熬锛屼絾鏄紝鍦?Chrome73(閲戜笣闆€) 鐗堟湰涔嬪悗锛宎sync 鐨勬墽琛屼紭鍖栦簡锛屽畠浼氬湪 promise1 鍜?promise2 鐨勮緭鍑轰箣鍓嶆墽琛屻€傜瑪鑰呭ぇ姒備簡瑙d簡涓€涓嬪簲璇ユ槸鐢?PromiseResolve 瀵?await 杩涜浜嗕紭鍖栵紝鍑忓皯浜?Promise 鐨勫啀娆″垱寤猴紝鏈夊叴瓒g殑灏忎紮浼村彲浠ョ湅鐪?Chrome 鐨勬簮鐮併€?/p>
浜斻€丯ode 涓殑 Event Loop
Node 涓篃鏈夊畯浠诲姟鍜屽井浠诲姟锛屼笌娴忚鍣ㄤ腑鐨勪簨浠跺惊鐜被浼笺€侼ode 涓庢祻瑙堝櫒浜嬩欢寰幆涓嶅悓锛屽叾涓湁澶氫釜瀹忎换鍔¢槦鍒楋紝鑰屾祻瑙堝櫒鏄彧鏈変竴涓畯浠诲姟闃熷垪銆?/p>
Node 鐨勬灦鏋勫簳灞傛槸鏈?libuv锛屽畠鏄?Node 鑷韩鐨勫姩鍔涙潵婧愪箣涓€锛岄€氳繃瀹冨彲浠ュ幓璋冪敤涓€浜涘簳灞傛搷浣滐紝Node 涓殑 Event Loop 鍔熻兘灏辨槸鍦?libuv 涓皝瑁呭疄鐜扮殑銆?/p>
瀹忎换鍔″拰寰换鍔?/h2>
Node 涓殑瀹忎换鍔″拰寰换鍔″湪娴忚鍣ㄧ鐨?JS 鐩告瘮澧炲姞浜嗕竴浜涳紝杩欓噷鍙垪鍑烘祻瑙堝櫒绔病鏈夌殑锛?/p>
-
瀹忎换鍔? -
setImmediate -
寰换鍔? -
process.nextTick
浜嬩欢寰幆鏈哄埗鐨勫叚涓樁娈?/h2>
鍏釜闃舵
Node 鐨勪簨浠跺惊鐜垎鎴愪簡鍏釜闃舵锛屾瘡涓樁娈靛搴斾竴涓畯浠诲姟闃熷垪锛岀浉褰撲簬鏄畯浠诲姟杩涜浜嗕竴涓垎绫汇€?/p>
-
timers(璁℃椂鍣?
鎵ц setTimeout 浠ュ強 setInterval 鐨勫洖璋? -
I/O callbacks
澶勭悊缃戠粶銆佹祦銆乀CP 鐨勯敊璇洖璋? -
idel, prepare --- 闂茬疆闃舵
node 鍐呴儴浣跨敤 -
poll(杞惊)
鎵ц poll 涓殑 I/O 闃熷垪锛屾鏌ュ畾鏃跺櫒鏄惁鍒版椂闂? -
check(妫€鏌?
瀛樻斁 setImmediate 鍥炶皟 -
close callbacks
鍏抽棴鍥炶皟锛屼緥濡?sockect.on('close')
杞惊椤哄簭
鎵ц鐨勮疆寰『搴?--- 姣忎釜闃舵閮借绛夊搴旂殑瀹忎换鍔¢槦鍒楁墽琛屽畬姣曟墠浼氳繘鍏ュ埌涓嬩竴涓樁娈电殑瀹忎换鍔¢槦鍒?/p>
-
timers -
I/O callbacks -
poll -
setImmediate -
close events
姣忎袱涓樁娈典箣闂存墽琛屽井浠诲姟闃熷垪
Event Loop 杩囩▼
-
鎵ц鍏ㄥ眬鐨?script 鍚屾浠g爜 -
鎵ц寰换鍔¢槦鍒楋紝鍏堟墽琛屾墍鏈?Next Tick 闃熷垪涓殑鎵€鏈変换鍔★紝鍐嶆墽琛屽叾浠栫殑寰换鍔¢槦鍒椾腑鐨勬墍鏈変换鍔? -
寮€濮嬫墽琛屽畯浠诲姟锛屽叡鍏釜闃舵锛屼粠绗竴涓樁娈靛紑濮嬫墽琛岃嚜宸卞畯浠诲姟闃熷垪涓殑鎵€鏈変换鍔?娴忚鍣ㄦ槸浠庡畯浠诲姟闃熷垪涓彇绗竴涓墽琛岋紒锛? -
姣忎釜闃舵鐨勫畯浠诲姟鎵ц瀹屾瘯涔嬪悗锛屽紑濮嬫墽琛屽井浠诲姟 -
TimersQueue -> 姝ラ2 -> I/O Queue -> 姝ラ2 -> Check Queue -> 姝ラ2 -> Close Callback Queue -> 姝ラ2 -> TimersQueue ...
杩欓噷瑕佹敞鎰忕殑鏄紝nextTick 浜嬩欢鏄竴涓崟鐙殑闃熷垪锛屽畠鐨勪紭鍏堢骇浼氶珮浜庡井浠诲姟锛屾墍浠ュ湪褰撳墠瀹忎换鍔?鍚屾浠诲姟鎵ц瀹屾垚涔嬪悗锛屼細鍏堟墽琛?nextTick 闃熷垪涓殑鎵€鏈変换鍔★紝鍐嶅幓鎵ц寰换鍔¢槦鍒椾腑鐨勬墍鏈変换鍔°€?/p>
setTimeout 鍜?setImmediate
鍦ㄨ繖閲岃鍗曠嫭璇翠竴涓?setTimeout 鍜?setImmediate锛宻etTimeout 瀹氭椂鍣ㄥ緢鐔熸倝锛岄偅灏辫璇?setImmediate
setImmediate() 鏂规硶鐢ㄤ簬鎶婁竴浜涢渶瑕侀暱鏃堕棿杩愯鐨勬搷浣滄斁鍦ㄤ竴涓洖璋冨嚱鏁伴噷锛屽苟鍦ㄦ祻瑙堝櫒瀹屾垚鍏朵粬鎿嶄綔锛堝浜嬩欢鍜屾樉绀烘洿鏂帮級鍚庣珛鍗宠繍琛屽洖璋冨嚱鏁般€備粠瀹氫箟鏉ョ湅灏辨槸涓轰簡闃叉涓€浜涜€楁椂闀跨殑鎿嶄綔闃诲鍚庨潰鐨勬搷浣滐紝杩欎篃鏄负浠€涔?check 闃舵杩愯椤哄簭鎺掔殑姣旇緝鍚庛€?/p>
涓句釜鏍楀瓙
鎴戜滑鏉ョ湅杩欐牱鐨勪竴涓緥瀛愶細
setTimeout(() => {
console.log('setTimeout')
}, 0)
setImmediate(() => {
console.log('setImmediate')
})
杩欓噷娑夊強 timers 闃舵鍜?check 闃舵锛屾寜鐓т笂闈㈢殑杩愯椤哄簭鏉ヨ锛宼imers 闃舵鏄湪绗竴涓墽琛岀殑锛屼細鏃╀簬 check 闃舵銆傝繍琛岃繖娈电▼搴忓彲浠ョ湅鍒板涓嬬殑缁撴灉锛?/p>
鍙槸鍐嶅杩愯鍑犳锛屼綘灏变細鐪嬪埌濡備笅鐨勭粨鏋滐細
setImmediate 鐨勮緭鍑鸿窇鍒?setTimeout 鍓嶉潰鍘讳簡锛岃繖鏃跺€欏氨鏄細灏忔湅鍙嬩綘鏄惁鏈夊緢澶氱殑闂彿鉂?/p>
鍒嗘瀽
鎴戜滑鏉ュ垎鏋愪竴涓嬪師鍥狅紝timers 闃舵纭疄鏄湪 check 闃舵涔嬪墠锛屼絾鏄湪 timers 闃舵鏃跺€欙紝杩欓噷鐨?setTimeout 鐪熺殑鍒颁簡鎵ц鐨勬椂闂村悧锛?/p>
杩欓噷灏辫鍏堢湅鐪?setTiemout(fn, 0)
锛岃繖涓鍙ョ殑鎰忔€濅笉鏄寚涓嶅欢杩熺殑鎵ц锛岃€屾槸鎸囧湪鍙互鎵ц setTimeout 鐨勬椂鍊欏氨绔嬪嵆鎵ц瀹冪殑鍥炶皟锛屼篃灏辨槸澶勭悊瀹屽綋鍓嶄簨浠剁殑鏃跺€欑珛鍗虫墽琛屽洖璋冦€?/p>
鍦?Node 涓?setTimeout 绗簩涓椂闂村弬鏁扮殑鏈€灏忓€兼槸 1ms锛屽皬浜?1ms 浼氳鍒濆鍖栦负 1(娴忚鍣ㄤ腑鏈€灏忓€兼槸 4ms)锛屾墍浠ュ湪杩欓噷 setTimeout(fn, 0) === setTimeout(fn, 1)
setTimeout 鐨勫洖璋冨嚱鏁板湪 timers 闃舵鎵ц锛宻etImmediate 鐨勫洖璋冨嚱鏁板湪 check 闃舵鎵ц锛孍vent Loop 鐨勫紑濮嬩細鍏堟鏌?timers 闃舵锛屼絾鏄湪浠g爜寮€濮嬭繍琛屼箣鍓嶅埌 timers 闃舵(浠g爜鐨勫惎鍔ㄣ€佽繍琛?浼氭秷鑰椾竴瀹氱殑鏃堕棿锛屾墍浠ヤ細鍑虹幇涓ょ鎯呭喌锛?/p>
-
timers 鍓嶇殑鍑嗗鏃堕棿瓒呰繃 1ms锛屾弧瓒?loop -> timers >= 1锛宻etTimeout 鐨勬椂閽熷懆鏈熷埌浜嗭紝鍒欐墽琛?timers 闃舵(setTimeout)鐨勫洖璋冨嚱鏁?/p>
-
timers 鍓嶇殑鍑嗗鏃堕棿灏忎簬 1ms锛岃繕娌″埌 setTimeout 棰勮鐨勬椂闂达紝鍒欏厛鎵ц check 闃舵(setImmediate)鐨勫洖璋冨嚱鏁帮紝涓嬩竴娆?Event Loop 鍐嶈繘鍏?timers 闃舵鎵ц timer 闃舵(setTimeout)鐨勫洖璋冨嚱鏁?/p>
鏈€寮€濮嬪氨璇翠簡锛屼竴涓紭绉€鐨勭▼搴忓憳瑕佽鑷繁鐨勪唬鐮佹寜鐓ц嚜宸辨兂瑕佺殑椤哄簭杩愯锛屼笅闈㈡垜浠氨鏉ユ帶鍒朵竴涓?setTimeout 鍜?setImediate 鐨勮繍琛屻€?/p>
-
璁?setTimeout 鍏堟墽琛?
涓婇潰浠g爜杩愯椤哄簭涓嶅悓鏃犻潪灏辨槸鍥犱负 Node 鍑嗗鏃堕棿鐨勪笉纭畾鎬э紝鎴戜滑鍙互鐩存帴鎵嬪姩寤堕暱鍑嗗鏃堕棿馃憞
const start = Date.now()
while (Date.now() - start < 10)
setTimeout(() => {
console.log('setTimeout')
}, 0)
setImmediate(() => {
console.log('setImmediate')
})
-
璁?setImmediate 鍏堟墽琛?br>setImmediate 鏄湪 check 闃舵鎵ц锛岀浉瀵逛簬 setTimeout 鏉ヨ鏄湪 timers 闃舵涔嬪悗锛屽彧闇€瑕佹兂鍔炴硶鎶婄▼搴忕殑杩愯鐜鎺у埗鍦?timers 闃舵涔嬪悗灏卞彲浠ヤ簡銆?/p>
璁╃▼搴忚嚦灏戜粠 I/O callbacks 闃舵寮€濮?--- 鍙互濂椾竴灞傛枃浠惰鍐欐妸鎶婄▼搴忔帶鍒跺湪 I/O callbacks 闃舵鐨勮繍琛岀幆澧冧腑馃憞
const fs = require('fs')
fs.readFile(__dirname, () => {
setTimeout(() => {
console.log('setTimeout')
}, 0)
setImmediate(() => {
console.log('setImmediate')
})
})
Node 11.x 鐨勫彉鍖?/h2>
timers 闃舵鐨勬墽琛屾湁鎵€鍙樺寲
setTimeout(() => console.log('timeout1'))
setTimeout(() => {
console.log('timeout2')
Promise.resolve().then(() => console.log('promise resolve'))
})
-
node 10 鍙婁箣鍓嶇殑鐗堟湰锛?br>瑕佽€冭檻涓婁竴涓畾鏃跺櫒鎵ц瀹屾垚鏃讹紝涓嬩竴涓畾鏃跺櫒鏄惁鍒版椂闂村姞鍏ヤ簡浠诲姟闃熷垪涓紝濡傛灉鏈埌鏃堕棿锛屽厛鎵ц鍏朵粬鐨勪唬鐮併€?br>姣斿锛?br>timer1 鎵ц瀹屼箣鍚?timer2 鍒颁簡浠诲姟闃熷垪涓紝椤哄簭涓?
timer1 -> timer2 -> promise resolve
timer2 鎵ц瀹屼箣鍚?timer2 杩樻病鍒颁换鍔¢槦鍒椾腑锛岄『搴忎负timer1 -> promise resolve -> timer2
-
node 11 鍙婂叾涔嬪悗鐨勭増鏈細
timeout1 -> timeout2 -> promise resolve
涓€鏃︽墽琛屾煇涓樁娈甸噷鐨勪竴涓畯浠诲姟涔嬪悗灏辩珛鍒绘墽琛屽井浠诲姟闃熷垪锛岃繖鍜屾祻瑙堝櫒绔繍琛屾槸涓€鑷寸殑銆?/p>
灏忕粨
Node 鍜岀娴忚鍣ㄧ鏈変粈涔堜笉鍚?/p>
-
娴忚鍣ㄧ鐨?Event Loop 鍜?Node.js 涓殑 Event Loop 鏄笉鍚岀殑锛屽疄鐜版満鍒朵篃涓嶄竴鏍? -
Node.js 鍙互鐞嗚В鎴愭湁4涓畯浠诲姟闃熷垪鍜?涓井浠诲姟闃熷垪锛屼絾鏄墽琛屽畯浠诲姟鏃舵湁6涓樁娈? -
Node.js 涓檺鍒舵€у叏灞€ script 浠g爜锛屾墽琛屽畬鍚屾浠g爜鍚庯紝鍏堜粠寰换鍔¢槦鍒?Next Tick Queue 涓彇鍑烘墍鏈変换鍔℃斁鍏ヨ皟鐢ㄦ爤鎵ц锛屽啀浠庡叾浠栧井浠诲姟闃熷垪涓彇鍑烘墍鏈変换鍔℃斁鍏ヨ皟鐢ㄦ爤涓墽琛岋紝鐒跺悗寮€濮嬪畯浠诲姟鐨?涓樁娈碉紝姣忎釜闃舵閮藉皢鍏跺畯浠诲姟闃熷垪涓殑鎵€鏈変换鍔¢兘鍙栧嚭鏉ユ墽琛?娴忚鍣ㄦ槸鍙彇绗竴涓墽琛?锛屾瘡涓畯浠诲姟闃舵鎵ц瀹屾瘯涔嬪悗寮€濮嬫墽琛屽井浠诲姟锛屽啀寮€濮嬫墽琛屼笅涓€闃舵瀹忎换鍔★紝浠ユ鏋勬垚浜嬩欢寰幆 -
瀹忎换鍔″寘鎷?.... -
寰换鍔″寘鎷?....
鐪嬪埌杩欓噷锛屼綘搴旇瀵规祻瑙堝櫒绔拰 Node 绔殑 Event Loop 鏈変簡涓€瀹氱殑浜嗚В锛岄偅灏辩暀涓€涓鐩€?/p>
涓嶇洿鎺ユ斁浠g爜鏄兂璁╁ぇ瀹跺厛鑷繁鎬濊€冪劧鍚庡湪鏁蹭唬鐮佽繍琛屼竴閬崀
鏈€鍚庡涓€鍢?span class="mq-461">
鏈枃鍒拌繖閲岀畻鏄粨鏉熶簡锛岃繕鏄偅鍙ヨ瘽锛屽仛涓€涓▼搴忓憳瑕佺煡鍏剁劧鏇磋鐭ュ叾鎵€浠ョ劧銆傛垜鍐欎簺鏂囩珷涔熸槸鎯虫妸鐭ヨ瘑杈撳嚭锛屾楠岃嚜宸辨槸涓嶆槸鐪熺殑瀛︽噦浜嗐€傛枃绔犱腑鍙兘杩樺瓨鍦ㄤ竴浜涙病鏈夎娓呮鐨勫湴鏂规垨鑰呮槸鏈夐敊鐨勫湴鏂癸紝娆㈣繋鐩存帴鎸囧嚭~
鎴戞妸鎴戠殑瀛︿範璁板綍閮借褰曞湪浜嗘垜鐨?github 骞朵笖浼氭寔缁殑鏇存柊涓嬪幓锛屾湁鍏磋叮鐨勫皬浼欎即鍙互鐪嬬湅~
github[4]
鍙傝€冭祫鏂?/span>
鍗氬閾炬帴: https://tearill.github.io/
[2]Wikipedia: https://en.wikipedia.org/wiki/Event_loop
[3]JS 澶т細: https://www.bilibili.com/video/BV1bE411B7ez?t=478
[4]github: https://github.com/tearill/Reading_Record
鈼?nbsp;
鈼?nbsp;
鈼?nbsp;
路END路
姹囪仛绮惧僵鐨勫厤璐瑰疄鎴樻暀绋?/span>
鍠滄鏈枃锛岀偣涓€?span>鍦ㄧ湅鈥濆憡璇夋垜
以上是关于浣犱笉鐭ラ亾鐨?Event Loop的主要内容,如果未能解决你的问题,请参考以下文章