成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

JavaScript事件循環(huán)

Corwien / 2315人閱讀

摘要:事件循環(huán)當(dāng)主線(xiàn)程中的任務(wù)執(zhí)行完畢后,會(huì)從任務(wù)隊(duì)列中獲取任務(wù)一個(gè)個(gè)的放在棧中執(zhí)行去執(zhí)行,這個(gè)過(guò)程是循環(huán)不斷的,所以整個(gè)的這種運(yùn)行機(jī)制又稱(chēng)為事件循環(huán)。

寫(xiě)在前面

說(shuō)起javascript(以下簡(jiǎn)稱(chēng)js)這門(mén)語(yǔ)言,相信大家已經(jīng)非常熟悉了,不管是前端開(kāi)發(fā)還是后端開(kāi)發(fā)幾乎無(wú)時(shí)無(wú)刻都要跟它打交道。雖說(shuō)開(kāi)發(fā)者每天幾乎都要操作js,但是你真的確定你掌握了js的運(yùn)行機(jī)制嗎!下面我們就來(lái)聊聊這話(huà)題。

JavaScript運(yùn)行機(jī)制圖解

上圖我們可以分為兩部分:瀏覽器中的JS引擎運(yùn)行環(huán)境Runtime,那它們的區(qū)別是什么?

JS引擎:編譯并執(zhí)行代碼的地方。

如上圖中可以看出JS引擎分為兩大核心部分:棧和堆

棧(Stack):js代碼的執(zhí)行都要壓到此棧中執(zhí)行。

堆:存放對(duì)象、數(shù)組的地方,js垃圾回收就是檢查這里。

Runtime:瀏覽器的運(yùn)行環(huán)境,它提供了一些對(duì)外接口供JS調(diào)用,如網(wǎng)絡(luò)請(qǐng)求接口。

JavaScript引擎是單線(xiàn)程的

JS引擎是單線(xiàn)程的,也就是說(shuō)在一個(gè)時(shí)間段內(nèi),事情只能一件一件的按先后順序去做,第一件事沒(méi)做完就不能第二件事。那么在js引擎中負(fù)責(zé)解釋和執(zhí)行js代碼的線(xiàn)程只有一個(gè),我們可以稱(chēng)之為主線(xiàn)程。

當(dāng)然瀏覽器的運(yùn)行環(huán)境Runtime還提供一些其他的線(xiàn)程,如定時(shí)器線(xiàn)程、ajax線(xiàn)程、事件線(xiàn)程、網(wǎng)絡(luò)請(qǐng)求和UI渲染的線(xiàn)程,為了和js主線(xiàn)程分開(kāi),我們這里都統(tǒng)稱(chēng)它們?yōu)?b>工作線(xiàn)程。

由于瀏覽器是多線(xiàn)程的,所以工作線(xiàn)程和js主線(xiàn)程都可以執(zhí)行任務(wù),線(xiàn)程間互不干擾。

JavaScript同步(異步)任務(wù)

在JavaScript任務(wù)可以分為兩種:

同步任務(wù):在主線(xiàn)程上排隊(duì)執(zhí)行的任務(wù),只有前一個(gè)任務(wù)執(zhí)行完畢,才能執(zhí)行后一個(gè)任務(wù),若前一個(gè)任務(wù)耗費(fèi)很長(zhǎng)時(shí)間,則后面的任務(wù)會(huì)一直處于等待狀態(tài),即阻塞狀態(tài)。

異步任務(wù):在棧執(zhí)行代碼的過(guò)程中,如遇到異步函數(shù),如setTimeout、異步Ajax、事件處理程序,會(huì)將這些異步代碼交給瀏覽器的工作線(xiàn)程來(lái)處理,我們把這些任務(wù)稱(chēng)之為異步任務(wù)。異步任務(wù)是不進(jìn)入主線(xiàn)程,而是進(jìn)入任務(wù)隊(duì)列(queue task)。

什么異步函數(shù)?

異步函數(shù)通常是由發(fā)起函數(shù)回調(diào)函數(shù)構(gòu)成的。如:

A(callback)

函數(shù)A就是發(fā)起函數(shù)

callback就是回調(diào)函數(shù)

?

它們都是在主線(xiàn)程調(diào)用的,其中發(fā)起函數(shù)用來(lái)發(fā)起異步過(guò)程,回調(diào)函數(shù)用來(lái)處理結(jié)果。

如:`setTimeout(callback,1000)`

setTimeout就是發(fā)起函數(shù)、callback就是回調(diào)函數(shù)。

如:異步的Ajax
    var xhr = new new XMLHttpRequest();
    xhr.onreadystatechange = callback; //callback為回調(diào)函數(shù)
    xhr.open("get",url,true);
    xhr.send(null); // send為發(fā)起函數(shù)

可以看出發(fā)起函數(shù)和回調(diào)函數(shù)也可以是分離的。

?

既然同步任務(wù)是在主線(xiàn)程中執(zhí)行的,那么異步任務(wù)何時(shí)執(zhí)行?

答:是這樣的,一旦棧中同步任務(wù)執(zhí)行完畢后,系統(tǒng)就會(huì)通過(guò)事件循環(huán)機(jī)制讀取任務(wù)隊(duì)列中的任務(wù)一個(gè)個(gè)移到棧中去執(zhí)行。

?

事件循環(huán)

當(dāng)主線(xiàn)程中的任務(wù)執(zhí)行完畢后,會(huì)從任務(wù)隊(duì)列中獲取任務(wù)一個(gè)個(gè)的放在棧中執(zhí)行去執(zhí)行,這個(gè)過(guò)程是循環(huán)不斷的,所以整個(gè)的這種運(yùn)行機(jī)制又稱(chēng)為事件循環(huán)。

在js中,代碼最終都是在棧中執(zhí)行的,棧結(jié)構(gòu)的特點(diǎn)是:先進(jìn)后出,后進(jìn)先出。

我們來(lái)看下面代碼的運(yùn)行結(jié)果:

function bar(){
    console.log(1);
    foo();
}

function foo(){
    par();
    console.log(3);
}

function par(){
    setTimeout(function(){
        console.log(2);
    },0);
}

bar();

運(yùn)行的最終結(jié)果是:132。 為什么結(jié)果不是123呢?

下我們來(lái)分析下代碼運(yùn)行時(shí)入棧和出棧的過(guò)程。

首先當(dāng)調(diào)用函數(shù)bar()時(shí),此函數(shù)就會(huì)先入棧,其內(nèi)部的console.log(1)也會(huì)隨之入棧執(zhí)行。

執(zhí)行完console.log(1)后,就要出棧,于是控制臺(tái)先打印出結(jié)果1,只剩下bar()在棧中。接著再執(zhí)行函數(shù)bar內(nèi)部的函數(shù)foo,于是函數(shù)foo也開(kāi)心的入棧了。

執(zhí)行函數(shù)foo的內(nèi)部代碼,調(diào)用函數(shù)par(),于是函數(shù)par()也要跟著入棧。

由于函數(shù)par()內(nèi)部執(zhí)行遇到了異步函數(shù)setTimeout,異步函數(shù)則會(huì)由瀏覽器的Runtime運(yùn)行環(huán)境的工作線(xiàn)程來(lái)處理,等定時(shí)器設(shè)置的時(shí)間到達(dá)就會(huì)被放到任務(wù)隊(duì)列中,此時(shí)棧的同步任務(wù)繼續(xù)執(zhí)行。

接著在執(zhí)行par函數(shù)中的console.log(3),控制臺(tái)打印結(jié)果為3 ,此時(shí)棧的代碼執(zhí)行完畢后,會(huì)按照棧的特點(diǎn)進(jìn)行

先進(jìn)后出,后進(jìn)先出順序進(jìn)行出棧。出棧順序:先函數(shù)par()-->后函數(shù)foo()-->最后函數(shù)bar

最后只剩下異步任務(wù),由主線(xiàn)程去獲取任務(wù)隊(duì)列中的任務(wù)放在棧中去執(zhí)行。也可以認(rèn)為棧中的同步代碼執(zhí)行總是在讀取異步任務(wù)之前執(zhí)行。

最后執(zhí)行setTimeout中的回調(diào)函數(shù):結(jié)果控制臺(tái)輸出為2。

setTimeout(function(){
        console.log(2);
},0);

所以代碼的最終運(yùn)行結(jié)果為132。

小結(jié)

js引擎是單線(xiàn)程執(zhí)行js代碼,同步任務(wù)在棧中按順序執(zhí)行,如果某一個(gè)同步任務(wù)沒(méi)有執(zhí)行完畢,則后面的代碼將會(huì)處于阻塞等待狀態(tài)

棧中若執(zhí)行遇到了異步任務(wù)(如定時(shí)器、異步Ajax、事件),會(huì)將此異步任務(wù)通過(guò)瀏覽器對(duì)應(yīng)的工作線(xiàn)程來(lái)處理。

工作線(xiàn)程中的所有異步任務(wù)均會(huì)按照設(shè)定的時(shí)間進(jìn)行等待,時(shí)間一到會(huì)被加入任務(wù)隊(duì)列。如果是異步ajax,則等待其返回結(jié)果后在加入到任務(wù)隊(duì)列

當(dāng)棧中為空時(shí),會(huì)通過(guò)事件循環(huán)來(lái)一個(gè)個(gè)獲取任務(wù)隊(duì)列中的任務(wù)放到棧中進(jìn)行逐個(gè)運(yùn)行。即棧中的同步任務(wù)總是在讀取異步任務(wù)之前執(zhí)行

定時(shí)器設(shè)置的時(shí)間不一定按照設(shè)定的時(shí)間進(jìn)行執(zhí)行,這得取決于棧中同步任務(wù)耗費(fèi)的時(shí)間。因?yàn)闂V袌?zhí)行的同步任務(wù)如果耗費(fèi)很長(zhǎng)時(shí)間,則會(huì)影響到異步任務(wù)回調(diào)函數(shù)的執(zhí)行。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/94222.html

相關(guān)文章

  • 什么是JavaScript 事件循環(huán) ?

    摘要:此事件隊(duì)列的美妙之處在于它只是函數(shù)等待被調(diào)用和移動(dòng)到調(diào)用棧的一個(gè)臨時(shí)存放區(qū)域。在事件循環(huán)不斷監(jiān)視調(diào)用棧是否為空現(xiàn)在確實(shí)是空的時(shí)候調(diào)用創(chuàng)建一個(gè)新的調(diào)用棧來(lái)執(zhí)行代碼。在執(zhí)行完之后進(jìn)入了一個(gè)新的狀態(tài)這個(gè)狀態(tài)調(diào)用棧為空事件記錄表為空事件隊(duì)列也為空。 這篇文章是對(duì)個(gè)人認(rèn)為講解 JavaScript 事件循環(huán)比較清楚的一篇英文文章的簡(jiǎn)單翻譯,原文地址是http://altitudelabs.com...

    tracymac7 評(píng)論0 收藏0
  • JavaScript運(yùn)行機(jī)制和事件循環(huán)

    摘要:主線(xiàn)程不斷重復(fù)上面的三步,此過(guò)程也就是常說(shuō)的事件循環(huán)。所以主線(xiàn)程代碼執(zhí)行時(shí)間過(guò)長(zhǎng),會(huì)阻塞事件循環(huán)的執(zhí)行。參考資料這一次,徹底弄懂執(zhí)行機(jī)制任務(wù)隊(duì)列的順序機(jī)制事件循環(huán)搞懂異步事件輪詢(xún)與中的事件循環(huán) 1. 說(shuō)明 讀過(guò)本文章后,您能知道: JavaScript代碼在瀏覽器中的執(zhí)行機(jī)制和事件循環(huán) 面試中經(jīng)常遇到的代碼輸出順序問(wèn)題 首先通過(guò)一段代碼來(lái)驗(yàn)證你是否了解代碼輸出順序,如果你不知道輸出...

    Ververica 評(píng)論0 收藏0
  • 總結(jié)javascript基礎(chǔ)概念(二):事件隊(duì)列循環(huán)

    摘要:而事件循環(huán)是主線(xiàn)程中執(zhí)行棧里的代碼執(zhí)行完畢之后,才開(kāi)始執(zhí)行的。由此產(chǎn)生的異步事件執(zhí)行會(huì)作為任務(wù)隊(duì)列掛在當(dāng)前循環(huán)的末尾執(zhí)行。在下,觀(guān)察者基于監(jiān)聽(tīng)事件的完成情況在下基于多線(xiàn)程創(chuàng)建。 主要問(wèn)題: 1、JS引擎是單線(xiàn)程,如何完成事件循環(huán)的? 2、定時(shí)器函數(shù)為什么計(jì)時(shí)不準(zhǔn)確? 3、回調(diào)與異步,有什么聯(lián)系和不同? 4、ES6的事件循環(huán)有什么變化?Node中呢? 5、異步控制有什么難點(diǎn)?有什么解決方...

    zhkai 評(píng)論0 收藏0
  • JavaScript單線(xiàn)程事件循環(huán)(Event Loop)那些事

    摘要:概述本篇主要介紹的運(yùn)行機(jī)制單線(xiàn)程事件循環(huán)結(jié)論先在中利用運(yùn)行至完成和非阻塞完成單線(xiàn)程下異步任務(wù)的處理就是先處理主模塊主線(xiàn)程上的同步任務(wù)再處理異步任務(wù)異步任務(wù)使用事件循環(huán)機(jī)制完成調(diào)度涉及的內(nèi)容有單線(xiàn)程事件循環(huán)同步執(zhí)行異步執(zhí)行定時(shí)器的事件循環(huán)開(kāi)始 1.概述 本篇主要介紹JavaScript的運(yùn)行機(jī)制:單線(xiàn)程事件循環(huán)(Event Loop). 結(jié)論先: 在JavaScript中, 利用運(yùn)行至...

    Shisui 評(píng)論0 收藏0
  • 事件循環(huán)與任務(wù)隊(duì)列

    摘要:需要注意的是,定時(shí)器比較特殊,并沒(méi)有把回調(diào)函數(shù)掛在事件循環(huán)隊(duì)列中,它所做的就是設(shè)置一個(gè)定時(shí)器,當(dāng)定時(shí)器到時(shí)后,環(huán)境會(huì)把你的回調(diào)函數(shù)放在事件循環(huán)中,這樣,在未來(lái)某個(gè)時(shí)刻的會(huì)被取出執(zhí)行。 Author: bugall Wechat: bugallF Email: 769088641@qq.com Github: https://github.com/bugall 一...

    SQC 評(píng)論0 收藏0
  • JavaScript事件循環(huán)(Event Loop)

    摘要:事件循環(huán)的順序,決定代碼執(zhí)行的順序。輸出第二輪事件循環(huán)正式結(jié)束三第三輪事件循環(huán)第三輪事件循環(huán)從宏任務(wù)開(kāi)始。記為遇到,立即執(zhí)行回調(diào)函數(shù)放入中注冊(cè),然后被分發(fā)到微任務(wù)事件隊(duì)列中。 1、為什么要有事件循環(huán)? 因?yàn)閖s是單線(xiàn)程的,事件循環(huán)是js的執(zhí)行機(jī)制,也是js實(shí)現(xiàn)異步的一種方法。 既然js是單線(xiàn)程,那就像只有一個(gè)窗口的銀行,客戶(hù)需要排隊(duì)一個(gè)一個(gè)辦理業(yè)務(wù),同理js任務(wù)也要一個(gè)一個(gè)順序執(zhí)行。如...

    dmlllll 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<