您好,登錄后才能下訂單哦!
這篇文章主要講解了“JavaScript事件循環(huán)怎么使用”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“JavaScript事件循環(huán)怎么使用”吧!
JavaScript事件循環(huán)是一種機(jī)制,用于處理異步事件和回調(diào)函數(shù)。它是JavaScript運(yùn)行時(shí)環(huán)境的一部分,負(fù)責(zé)管理事件隊(duì)列和調(diào)用棧。
事件循環(huán)的基本原理是事件循環(huán)的核心是一個(gè)事件隊(duì)列,所有的事件都被放入這個(gè)隊(duì)列中,然后按照順序依次執(zhí)行。如果隊(duì)列為空,JavaScript會(huì)等待新的任務(wù)加入隊(duì)列。當(dāng)JavaScript代碼執(zhí)行時(shí),所有同步任務(wù)都會(huì)被立即執(zhí)行,而異步任務(wù)則會(huì)被放入事件隊(duì)列中。
當(dāng)所有同步任務(wù)執(zhí)行完畢后,事件循環(huán)會(huì)從事件隊(duì)列中取出一個(gè)任務(wù),并將其放入調(diào)用棧中執(zhí)行。當(dāng)該任務(wù)執(zhí)行完畢后,事件循環(huán)會(huì)再次從事件隊(duì)列中取出下一個(gè)任務(wù),并重復(fù)這個(gè)過(guò)程。
1、執(zhí)行同步代碼,直到遇到第一個(gè)異步事件(如setTimeout、setInterval、Promise等)。
2、將異步事件放入事件隊(duì)列中,并繼續(xù)執(zhí)行同步代碼。
3、當(dāng)所有同步代碼執(zhí)行完畢后,JavaScript引擎會(huì)檢查事件隊(duì)列中是否有事件需要執(zhí)行。
4、如果事件隊(duì)列中有事件需要執(zhí)行,JavaScript引擎會(huì)將第一個(gè)事件取出來(lái),并執(zhí)行對(duì)應(yīng)的回調(diào)函數(shù)。
5、執(zhí)行完回調(diào)函數(shù)后,JavaScript引擎會(huì)再次檢查事件隊(duì)列中是否有事件需要執(zhí)行,如果有則重復(fù)步驟4,否則繼續(xù)等待新的事件加入事件隊(duì)列。
需要注意的是,事件循環(huán)是單線程的,也就是說(shuō)JavaScript引擎在同一時(shí)間只能執(zhí)行一個(gè)任務(wù)。
因此,如果一個(gè)任務(wù)執(zhí)行時(shí)間過(guò)長(zhǎng),會(huì)阻塞事件循環(huán),導(dǎo)致其他任務(wù)無(wú)法執(zhí)行。為了避免這種情況,可以將長(zhǎng)時(shí)間的任務(wù)拆分成多個(gè)小任務(wù),使用setTimeout或setInterval分批執(zhí)行。
另外,Promise也是基于事件循環(huán)的機(jī)制實(shí)現(xiàn)的。當(dāng)Promise狀態(tài)發(fā)生改變時(shí),會(huì)將對(duì)應(yīng)的回調(diào)函數(shù)放入微任務(wù)隊(duì)列中,等待當(dāng)前任務(wù)執(zhí)行完畢后立即執(zhí)行。因此,Promise的回調(diào)函數(shù)總是在當(dāng)前任務(wù)執(zhí)行完畢后立即執(zhí)行,而不會(huì)被放入事件隊(duì)列中等待執(zhí)行。
1、Promise
:Promise是一種異步編程的解決方案,它可以將異步操作轉(zhuǎn)化為同步操作的形式,使得代碼更加簡(jiǎn)潔易懂。Promise的基本原理是將異步操作封裝成一個(gè)Promise對(duì)象,通過(guò)then方法來(lái)處理異步操作的結(jié)果。
2、async/await
:async/await是ES2017引入的一種異步編程的解決方案,它可以讓異步代碼看起來(lái)像同步代碼,使得代碼更加易讀易懂。async/await的基本原理是使用async關(guān)鍵字定義一個(gè)異步函數(shù),然后在函數(shù)內(nèi)部使用await關(guān)鍵字來(lái)等待異步操作的結(jié)果。
3、定時(shí)器:JavaScript中有兩種定時(shí)器,分別是setTimeout和setInterval。setTimeout用于在指定的時(shí)間后執(zhí)行一次任務(wù),而setInterval則用于每隔一段時(shí)間執(zhí)行一次任務(wù)。這兩種定時(shí)器都是異步任務(wù),會(huì)被放入任務(wù)隊(duì)列中等待執(zhí)行。
JavaScript中的任務(wù)按照不同緯度進(jìn)行區(qū)分主要分為同步任務(wù)和異步任務(wù)、宏任務(wù)和微任務(wù)。
1、 同步任務(wù)按照代碼順序執(zhí)行的任務(wù)。
2、 異步任務(wù)是在將來(lái)某個(gè)時(shí)間點(diǎn)執(zhí)行的任務(wù)。異步任務(wù)通常是由事件觸發(fā)器(如鼠標(biāo)點(diǎn)擊、網(wǎng)絡(luò)請(qǐng)求等)生成的。 當(dāng)一個(gè)異步任務(wù)被觸發(fā)時(shí),它會(huì)被放入任務(wù)隊(duì)列中等待執(zhí)行。
JavaScript事件循環(huán)的執(zhí)行順序可以用以下偽代碼表示:
while (queue.waitForMessage()) { queue.processNextMessage(); }
在這個(gè)偽代碼中,queue.waitForMessage()
表示等待隊(duì)列中有待執(zhí)行的任務(wù),queue.processNextMessage()
表示取出隊(duì)列中的下一個(gè)任務(wù)并執(zhí)行。
需要注意的是,JavaScript事件循環(huán)的執(zhí)行順序是不可中斷的。這意味著當(dāng)一個(gè)任務(wù)正在執(zhí)行時(shí),其他任務(wù)必須等待,直到當(dāng)前任務(wù)完成。因此,如果一個(gè)任務(wù)執(zhí)行時(shí)間過(guò)長(zhǎng),會(huì)導(dǎo)致其他任務(wù)無(wú)法及時(shí)執(zhí)行,從而影響應(yīng)用程序的性能和響應(yīng)速度。
1、宏任務(wù)包括setTimeout、setInterval、I/O操作等。
2、微任務(wù)包括Promise、MutationObserver等。
當(dāng)事件循環(huán)從事件隊(duì)列中取出一個(gè)任務(wù)時(shí),它會(huì)先執(zhí)行所有微任務(wù),然后再執(zhí)行一個(gè)宏任務(wù)。這個(gè)過(guò)程會(huì)一直重復(fù),直到事件隊(duì)列中的所有任務(wù)都被執(zhí)行完畢。
下面是一個(gè)例子:
console.log('1'); setTimeout(function() { console.log('2'); Promise.resolve().then(function() { console.log('3'); }); }, 0); Promise.resolve().then(function() { console.log('4'); }); console.log('5'); // 輸出結(jié)果為: 1 5 4 2 3
執(zhí)行順序:
執(zhí)行第一個(gè)console.log
,輸出1。
執(zhí)行setTimeout
,將其回調(diào)函數(shù)放入宏任務(wù)隊(duì)列中。
執(zhí)行Promise.resolve().then
,將其回調(diào)函數(shù)放入微任務(wù)隊(duì)列中。
執(zhí)行第二個(gè)console.log
,輸出5。
當(dāng)前任務(wù)執(zhí)行結(jié)束,執(zhí)行微任務(wù)隊(duì)列中的所有任務(wù),輸出4。
執(zhí)行宏任務(wù)隊(duì)列中的第一個(gè)任務(wù),即setTimeout
的回調(diào)函數(shù),輸出2。
執(zhí)行Promise.resolve().then
的回調(diào)函數(shù),輸出3。
需要注意的是,微任務(wù)和宏任務(wù)的執(zhí)行順序是固定的,即先執(zhí)行所有微任務(wù),再執(zhí)行宏任務(wù)。因此,如果在一個(gè)宏任務(wù)中產(chǎn)生了新的微任務(wù),那么這些微任務(wù)會(huì)在下一個(gè)宏任務(wù)執(zhí)行之前執(zhí)行。
下面是一個(gè)例子:
console.log('1'); setTimeout(function() { console.log('2'); Promise.resolve().then(function() { console.log('3'); }); }, 0); Promise.resolve().then(function() { console.log('4'); setTimeout(function() { console.log('5'); }, 0); }); console.log('6'); // 輸出結(jié)果為:1 6 4 2 3 5
執(zhí)行順序:
執(zhí)行第一個(gè)console.log
,輸出1。
執(zhí)行setTimeout
,將其回調(diào)函數(shù)放入宏任務(wù)隊(duì)列中。
執(zhí)行Promise.resolve().then
,將其回調(diào)函數(shù)放入微任務(wù)隊(duì)列中。
執(zhí)行第三個(gè)console.log
,輸出6。
當(dāng)前任務(wù)執(zhí)行結(jié)束,執(zhí)行微任務(wù)隊(duì)列中的所有任務(wù),輸出4。
執(zhí)行宏任務(wù)隊(duì)列中的第一個(gè)任務(wù),即setTimeout
的回調(diào)函數(shù),輸出2。
執(zhí)行Promise.resolve().then
的回調(diào)函數(shù),將setTimeout的回調(diào)函數(shù)放入宏任務(wù)隊(duì)列中。
當(dāng)前任務(wù)執(zhí)行結(jié)束,執(zhí)行微任務(wù)隊(duì)列中的所有任務(wù),輸出3。
執(zhí)行宏任務(wù)隊(duì)列中的第一個(gè)任務(wù),即setTimeout
的回調(diào)函數(shù),輸出5。
感謝各位的閱讀,以上就是“JavaScript事件循環(huán)怎么使用”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)JavaScript事件循環(huán)怎么使用這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。