本文章向大家介紹如何在javascript中使用event loop事件實(shí)現(xiàn)一個(gè)循環(huán)功能,主要包括如何在javascript中使用event loop事件實(shí)現(xiàn)一個(gè)循環(huán)功能的使用實(shí)例、應(yīng)用技巧、基本知識(shí)點(diǎn)總結(jié)和需要注意事項(xiàng),具有一定的參考價(jià)值,需要的朋友可以參考一下。
創(chuàng)新互聯(lián)公司于2013年成立,公司以網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)、系統(tǒng)開(kāi)發(fā)、網(wǎng)絡(luò)推廣、文化傳媒、企業(yè)宣傳、平面廣告設(shè)計(jì)等為主要業(yè)務(wù),適用行業(yè)近百種。服務(wù)企業(yè)客戶數(shù)千家,涉及國(guó)內(nèi)多個(gè)省份客戶。擁有多年網(wǎng)站建設(shè)開(kāi)發(fā)經(jīng)驗(yàn)。為企業(yè)提供專業(yè)的網(wǎng)站建設(shè)、創(chuàng)意設(shè)計(jì)、宣傳推廣等服務(wù)。 通過(guò)專業(yè)的設(shè)計(jì)、獨(dú)特的風(fēng)格,為不同客戶提供各種風(fēng)格的特色服務(wù)。
JavaScript是一種直譯式的腳本語(yǔ)言,其解釋器被稱為JavaScript引擎,是瀏覽器的一部分,JavaScript是被廣泛用于客戶端的腳本語(yǔ)言,最早是在HTML網(wǎng)頁(yè)上使用,用來(lái)給HTML網(wǎng)頁(yè)增加動(dòng)態(tài)功能。
console.log('0') setTimeout(function () { console.log('1'); }); new Promise(function(resolve,reject){ console.log('2') resolve(3) }).then(function(val){ console.log(val) }) console.log(4)
輸出結(jié)果: “0” “2” 4 3 “1”
今天主要是分析為什么輸出結(jié)果是這樣的?這就和 javascript 的執(zhí)行機(jī)制密切相關(guān)了.
Event Queue 和 Event Loop
javascript 是一門單線程的語(yǔ)言, 這就意味著在執(zhí)行代碼的時(shí)候, 都只有一個(gè)主線程來(lái)處理所有的任務(wù).
我們都知道 javascript 包括同步代碼和異步代碼, 那么 javascript 是怎么處理這兩種情況的呢?
同步和異步任務(wù)分別進(jìn)入不同的執(zhí)行 場(chǎng)所, 同步的進(jìn)入主線程,異步的進(jìn)入 Event Table 并注冊(cè)函數(shù)
當(dāng)指定的事情完成時(shí), Event Table 會(huì)將這個(gè)函數(shù)(回調(diào)函數(shù))移入 Event Queue
主線程內(nèi)的任務(wù)執(zhí)行完畢為空, 會(huì)去 Event Queue 讀取對(duì)應(yīng)的函數(shù),進(jìn)入主線程執(zhí)行
上述過(guò)程會(huì)不斷重復(fù), 也就是常說(shuō)的 Event Loop(事件循環(huán))
這里我們引進(jìn)了 Event Queue 事件隊(duì)列這一概念. 所有異步操作的回調(diào)都會(huì)進(jìn)入到這里. 然后等到主線程空閑, 就會(huì)從這里調(diào)取回調(diào)執(zhí)行.
setTimeout
setTimeout 相信大家都有使用過(guò), 可以延時(shí)執(zhí)行并且是異步執(zhí)行的.
但是有時(shí)候我們得到的結(jié)果往往是代碼實(shí)際執(zhí)行的時(shí)間比我們想要延時(shí)執(zhí)行的時(shí)間要久。這又是為什么呢?
這就和我們之前所說(shuō)的 Event Loop 有關(guān)了, 我們可以來(lái)具體看下 setTimeout 的執(zhí)行步驟:
setTimeout(function () { asyncFn() }, 1000); syncFn()
asyncFn 將異步執(zhí)行函數(shù)放在 Event Table, 并且開(kāi)始計(jì)時(shí)
開(kāi)始執(zhí)行 syncFn, 但是 syncFn 可能需要處理的內(nèi)容很多, 執(zhí)行時(shí)間超過(guò) 1 秒, 但是計(jì)時(shí)還在繼續(xù)
計(jì)時(shí)到達(dá) 1 秒, setTimeout 延時(shí)完成, asyncFn 進(jìn)入 Event Queue 事件隊(duì)列, 但是主線程還在執(zhí)行, 所以只能等待
syncFn 執(zhí)行完成, 此時(shí) asyncFn 從事件隊(duì)列中進(jìn)入主線程執(zhí)行
所以有時(shí)候會(huì)出現(xiàn)代碼實(shí)際執(zhí)行時(shí)間比延時(shí)時(shí)間長(zhǎng)的情況。
宏任務(wù)和微任務(wù)
之前我們說(shuō)過(guò)異步任務(wù)會(huì)進(jìn)入到事件隊(duì)列中, 不同類型的任務(wù)會(huì)進(jìn)入到不同的隊(duì)列中, 比如宏任務(wù)會(huì)進(jìn)入到宏任務(wù)隊(duì)列中, 微任務(wù)會(huì)進(jìn)入到微任務(wù)隊(duì)列中.
我們只要記住 當(dāng)當(dāng)前執(zhí)行棧執(zhí)行完畢時(shí)會(huì)立刻先處理所有微任務(wù)隊(duì)列中的事件,然后再去宏任務(wù)隊(duì)列中取出一個(gè)事件。同一次事件循環(huán)中,微任務(wù)永遠(yuǎn)在宏任務(wù)之前執(zhí)行
這時(shí)候我們就可以解釋一開(kāi)始的代碼執(zhí)行結(jié)果了:
主線程執(zhí)行按順序代碼
遇到 setTimeout, 回調(diào)進(jìn)入到宏任務(wù)隊(duì)列上
遇到 Promise, 立即執(zhí)行, then 函數(shù)進(jìn)入到微任務(wù)隊(duì)列
同步代碼執(zhí)行結(jié)束, 主線程檢查是否存在微任務(wù), 發(fā)現(xiàn) then, 執(zhí)行
微任務(wù)執(zhí)行完畢, 再去查找宏任務(wù) setTimeout, 執(zhí)行
setTimeout 執(zhí)行結(jié)束, 檢查是否存在微任務(wù), 不存在, 結(jié)束.
到此這篇關(guān)于如何在javascript中使用event loop事件實(shí)現(xiàn)一個(gè)循環(huán)功能的文章就介紹到這了,更多相關(guān)的內(nèi)容請(qǐng)搜索創(chuàng)新互聯(lián)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持創(chuàng)新互聯(lián)!