當(dāng)只需要一個(gè)簡(jiǎn)單的工作界面時(shí),JavaScript就很容易滿足需求。當(dāng)界面變得更加復(fù)雜時(shí),問題就開始了。在這里,需要對(duì)JavaScript有更深入的了解。重要的是,即使大型且復(fù)雜的界面也要保持快速和響應(yīng)。響應(yīng)性通常是通過使用異步功能來實(shí)現(xiàn)的。這意味著可以讓代碼同時(shí)執(zhí)行多項(xiàng)操作,而無需停止或阻塞主線程。在本文中,將嘗試盡可能簡(jiǎn)單地告訴有關(guān)JJavaScript中的事件循環(huán)概念和異步開發(fā)。開始學(xué)習(xí)JS時(shí),看起來似乎很艱巨,但實(shí)際上,一切都變得簡(jiǎn)單得多。
事件循環(huán)如何工作?
事件循環(huán)是每個(gè)JavaScript開發(fā)人員以一種或另一種方式遇到的事情之一。JavaScript提供了一個(gè)基于事件循環(huán)的并發(fā)模型,該循環(huán)執(zhí)行代碼,收集和處理事件以及執(zhí)行排隊(duì)的子任務(wù)。
讓我們看一個(gè)設(shè)置超時(shí)的例子:
我認(rèn)為不難猜測(cè)這些日志將以什么順序調(diào)用。讓我們檢查一下。
但是,讓我們看一下引擎蓋下發(fā)生的事情。在示例中,我正在使用這個(gè)有用的網(wǎng)站
程序啟動(dòng)時(shí),它將遍歷代碼行。當(dāng)遇到異步操作時(shí),解釋器將此操作引發(fā)到調(diào)用堆棧中。在堆棧中,它開始看起來像是某個(gè)設(shè)置的超時(shí)時(shí)間,并且看起來像是瀏覽器API。然后,它拋出設(shè)置超時(shí),并在Web API中注冊(cè)了一些匿名函數(shù),當(dāng)瀏覽器在5000秒后完成設(shè)置超時(shí)時(shí),將執(zhí)行該匿名函數(shù)。接下來,匿名函數(shù)進(jìn)入回調(diào)隊(duì)列。隊(duì)列中運(yùn)行無限循環(huán),循環(huán)遍歷其元素,如果檢測(cè)到函數(shù)準(zhǔn)備就緒,則會(huì)將其扔回到調(diào)用堆棧中并執(zhí)行。
因此,我們不會(huì)阻止代碼的工作。我們不僅在談?wù)撛O(shè)置超時(shí),而且在談?wù)撈渌惒讲僮鳎缗c服務(wù)器一起工作的事件偵聽器。
但是,如果將0作為第二個(gè)參數(shù)傳遞給超時(shí)集,會(huì)發(fā)生什么情況呢?一模一樣。讓我們來看看。
瀏覽器仍會(huì)將功能拖放到Web API中,并且程序?qū)⒗^續(xù)運(yùn)行。
讓我們也看看事件監(jiān)聽器是如何工作的。
如上所述,事件偵聽器也是一個(gè)異步事件,并轉(zhuǎn)到Web API。現(xiàn)在,您了解了取消訂閱事件的重要性。
宏任務(wù)
讓我們以相同的事件示例為例,嘗試單擊幾次按鈕。
我們看到了事件隊(duì)列。這是宏任務(wù)回調(diào)隊(duì)列,一個(gè)v8術(shù)語。根據(jù)先進(jìn)先出規(guī)則執(zhí)行隊(duì)列中的任務(wù)。
讓我們注意兩個(gè)細(xì)節(jié):
1.在引擎執(zhí)行任務(wù)期間,頁面的渲染永遠(yuǎn)不會(huì)發(fā)生。任務(wù)花費(fèi)多長(zhǎng)時(shí)間都沒有關(guān)系。僅在任務(wù)完成后才呈現(xiàn)對(duì)DOM的更改。
2.如果任務(wù)花費(fèi)很長(zhǎng)時(shí)間并且瀏覽器無法執(zhí)行其他任務(wù)或處理用戶事件。因此,一段時(shí)間后,瀏覽器為您提供了“殺死”長(zhǎng)期運(yùn)行的任務(wù)的功能。當(dāng)腳本包含大量復(fù)雜的計(jì)算或?qū)е聼o限循環(huán)的錯(cuò)誤時(shí),這是??可能的。
微型任務(wù)
我們可以在最后一個(gè)示例中看到微任務(wù)。執(zhí)行宏任務(wù)時(shí),宏任務(wù)中的函數(shù)將被放置在調(diào)用堆棧中。直到微任務(wù)在那里完成之后,新的宏任務(wù)才開始執(zhí)行。
多虧了JavaScript,我們可以編寫異步應(yīng)用程序而無需考慮數(shù)據(jù)完整性和數(shù)據(jù)一致性之類的多線程。如果我們要執(zhí)行耗時(shí)的操作,例如查詢數(shù)據(jù)庫并使用結(jié)果填充模板,則最好將其從主線程中推出并異步執(zhí)行任務(wù)。我們通過大量的回調(diào)和持續(xù)的上下文丟失來彌補(bǔ)這些好處。
根據(jù)任務(wù)的具體情況,可能會(huì)發(fā)現(xiàn)您將使用異步/等待,回調(diào)或不同技術(shù)的某種混合。實(shí)際上,選擇哪種異步開發(fā)方法的問題的答案取決于項(xiàng)目的具體情況。如果某種方法允許您使用易于維護(hù)的可讀代碼來解決問題,而其他團(tuán)隊(duì)成員也可以輕松理解,那么您就需要這種方法。
上述就是關(guān)于JavaScript中的事件循環(huán)概念和異步開發(fā)的全部?jī)?nèi)容,想了解更多關(guān)于JavaScript開發(fā)的信息,請(qǐng)繼續(xù)關(guān)注中培偉業(yè)。