国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript同步和異步

Eirunye / 2234人閱讀

摘要:異步如果在函數(shù)返回的時(shí)候,調(diào)用者還不能購(gòu)得到預(yù)期結(jié)果,而是將來(lái)通過(guò)一定的手段得到例如回調(diào)函數(shù),這就是異步。的意思是,將回調(diào)函數(shù)立刻插入消息隊(duì)列,等待執(zhí)行,而不是立即執(zhí)行。

大家好,我是wmingren,小伙伴們都知道JavaScript是單線程的語(yǔ)言,所謂的單線程呢就是指如果有多個(gè)任務(wù)就必須去排隊(duì),前面任務(wù)執(zhí)行完成后,后面任務(wù)再執(zhí)行。到這里我們就產(chǎn)生了一個(gè)疑問(wèn),既然是單線程的,又怎么會(huì)有異步操作呢?首先了解一下同步和異步的概念吧。
一、同步和異步

同步
如果在函數(shù)返回結(jié)果的時(shí)候,調(diào)用者能夠拿到預(yù)期的結(jié)果(就是函數(shù)計(jì)算的結(jié)果),那么這個(gè)函數(shù)就是同步的.
console.log("hello");//執(zhí)行后,獲得了返回結(jié)果

如果函數(shù)是同步的,即使調(diào)用函數(shù)執(zhí)行任務(wù)比較耗時(shí),也會(huì)一致等待直到得到執(zhí)行結(jié)果。如下面的代碼:

function wait(){
    var time = (new Date()).getTime();//獲取當(dāng)前的unix時(shí)間戳
    while((new Date()).getTime() - time > 5000){}
    console.log("5秒過(guò)去了");
}
wait();
console.log("慢死了");

上面代碼中,函數(shù)wait是一個(gè)耗時(shí)程序,持續(xù)5秒,在它執(zhí)行的這漫長(zhǎng)的5秒中,下面的console.log()函數(shù)只能等待,這就是同步。

異步
如果在函數(shù)返回的時(shí)候,調(diào)用者還不能購(gòu)得到預(yù)期結(jié)果,而是將來(lái)通過(guò)一定的手段得到(例如回調(diào)函數(shù)),這就是異步。例如ajax操作。  
如果函數(shù)是異步的,發(fā)出調(diào)用之后,馬上返回,但是不會(huì)馬上返回預(yù)期結(jié)果。調(diào)用者不必主動(dòng)等待,當(dāng)被調(diào)用者得到結(jié)果之后會(huì)通過(guò)回調(diào)函數(shù)主動(dòng)通知調(diào)用者。
二、單線程與多線程
了解完同步和異步之后,我們?cè)賮?lái)看看我們的問(wèn)題:?jiǎn)尉€程又怎么會(huì)有異步呢?  
JavaScript其實(shí)就是一門語(yǔ)言,說(shuō)是單線程還是多線程得結(jié)合具體運(yùn)行環(huán)境。眾所周知,js的運(yùn)行環(huán)境就是瀏覽器,具體由js引擎取解析和執(zhí)行。下面我們來(lái)了解下瀏覽器。
瀏覽器

一個(gè)瀏覽器通常由以下幾個(gè)常駐的線程:

渲染引擎線程,負(fù)責(zé)頁(yè)面的渲染

js引擎線程,負(fù)責(zé)js的解析和執(zhí)行

定時(shí)觸發(fā)器線程,處理setInterval和setTimeout

事件觸發(fā)線程,處理DOM事件

異步http請(qǐng)求線程,處理http請(qǐng)求

要注意的是渲染引擎和js引擎線程是不能同時(shí)進(jìn)行的。渲染線程在執(zhí)行任務(wù)的時(shí)候,js引擎線程會(huì)被掛起。因?yàn)槿羰窃阡秩卷?yè)面的時(shí)候,js處理了DOM,瀏覽器就不知道該聽誰(shuí)的了
JS引擎
通常講到瀏覽器的時(shí)候,我們會(huì)說(shuō)到兩個(gè)引擎:渲染引擎和JS引擎。
1、渲染引擎:Chrome/Safari/Opera用的是Webkit引擎,IE用的是Trdent引擎,F(xiàn)ireFox用的是Gecko引擎。不同的引擎對(duì)同一個(gè)樣式的實(shí)現(xiàn)不一致,就導(dǎo)致瀏覽器的兼容性問(wèn)題。
2、JS引擎:js引擎可以說(shuō)是js虛擬機(jī),負(fù)責(zé)解析js代碼的解析和執(zhí)行。通常有以下步驟:

詞法解析:將源代碼分解位有意義的分詞

語(yǔ)法分析:用語(yǔ)法分析器將分詞解析成語(yǔ)法樹

代碼生成:生成機(jī)器能運(yùn)行的代碼

代碼執(zhí)行

不同瀏覽器的js引擎也各不相同,Chrome用的是V8,F(xiàn)ireFox用的是SpiderMonkey,Safari用的是JavaScriptCore,IE用的是Chakra。  

之所以說(shuō)js是單線程就是因?yàn)闉g覽器運(yùn)行時(shí)只開啟一個(gè)js解釋器,原因是若有兩個(gè)線程操作DOM,瀏覽器就又暈了。

JavaScript是單線程的,但是瀏覽器不是單線程的。一些I/O操作,定時(shí)器的計(jì)時(shí)和事件監(jiān)聽是由其他線程完成的。

三、消息隊(duì)列與事件循環(huán)
由上面瀏覽器一篇的介紹可以知道,瀏覽器中多個(gè)線程的合作完成了異步的操作,那么異步的回調(diào)函數(shù)又是怎樣完成執(zhí)行的呢?  

這就需要了解消息隊(duì)列和事件循環(huán)了。

如上圖所示,左邊的棧存儲(chǔ)的是同步任務(wù),就是那些能立即執(zhí)行、不耗時(shí)的任務(wù),如變量和函數(shù)的初始化、事件的綁定等等那些不需要回調(diào)函數(shù)的操作都可歸為這一類。

右邊的堆用來(lái)存儲(chǔ)聲明的變量、對(duì)象。下面的隊(duì)列就是消息隊(duì)列,一旦某個(gè)異步任務(wù)有了響應(yīng)就會(huì)被推入隊(duì)列中。如用戶的點(diǎn)擊事件、瀏覽器收到服務(wù)的響應(yīng)和setTimeout中待執(zhí)行的事件,每個(gè)異步任務(wù)都和回調(diào)函數(shù)相關(guān)聯(lián)。

JS引擎線程用來(lái)執(zhí)行棧中的同步任務(wù),當(dāng)所有同步任務(wù)執(zhí)行完畢后,棧被清空,然后讀取消息隊(duì)列中的一個(gè)待處理任務(wù),并把相關(guān)回調(diào)函數(shù)壓入棧中,單線程開始執(zhí)行新的同步任務(wù)。

JS引擎線程從消息隊(duì)列中讀取任務(wù)是不斷循環(huán)的,每次棧被清空后,都會(huì)在消息隊(duì)列中讀取新的任務(wù),如果沒(méi)有新的任務(wù),就會(huì)等待,直到有新的任務(wù),這就叫事件循環(huán)。

上圖以AJAX異步請(qǐng)求為例,發(fā)起異步任務(wù)后,由AJAX線程執(zhí)行耗時(shí)的異步操作,而JS引擎線程繼續(xù)執(zhí)行堆中的其他同步任務(wù),直到堆中的所有異步任務(wù)執(zhí)行完畢。然后,從消息隊(duì)列中依次按照順序取出消息作為一個(gè)同步任務(wù)在JS引擎線程中執(zhí)行,那么AJAX的回調(diào)函數(shù)就會(huì)在某一時(shí)刻被調(diào)用執(zhí)行。

四、實(shí)例
最后來(lái)一個(gè)經(jīng)典的面試題來(lái)幫助大家理解js的同步和異步。
代碼如下:
//執(zhí)行下面這段代碼,執(zhí)行后,在 5s 內(nèi)點(diǎn)擊兩下,過(guò)一段時(shí)間(>5s)后,再點(diǎn)擊兩下,整個(gè)過(guò)程的輸出結(jié)果是什么?
setTimeout(function(){
    for(var i = 0; i < 100000000; i++){}
    console.log("timer a");
}, 0)

for(var j = 0; j < 5; j++){
    console.log(j);
}

setTimeout(function(){
    console.log("timer b");
}, 0)

function waitFiveSeconds(){
    var now = (new Date()).getTime();
    while(((new Date()).getTime() - now) < 5000){}
    console.log("finished waiting");
}

document.addEventListener("click", function(){
    console.log("click");
})

console.log("click begin");
waitFiveSeconds();

要想了解上述代碼的輸出結(jié)果,首先介紹下定時(shí)器。

setTimeout 的作用是在間隔一定的時(shí)間后,將回調(diào)函數(shù)插入消息隊(duì)列中,等棧中的同步任務(wù)都執(zhí)行完畢后,再執(zhí)行。因?yàn)闂V械耐饺蝿?wù)也會(huì)耗時(shí), 所以間隔的時(shí)間一般會(huì)大于等于指定的時(shí)間 。

setTimeout(fn, 0) 的意思是,將回調(diào)函數(shù)fn立刻插入消息隊(duì)列,等待執(zhí)行,而不是立即執(zhí)行。看一個(gè)例子:

setTimeout(function() {
    console.log("a")
}, 0)

for(let i=0; i<10000; i++) {}
console.log("b")
//打印結(jié)果,說(shuō)明回調(diào)函數(shù)沒(méi)有立即執(zhí)行,而是等待同步任務(wù)執(zhí)行完成后才執(zhí)行的
b a
下面來(lái)解釋一下面試題吧。

先執(zhí)行同步任務(wù),for循環(huán),然后是console.log("click begin") 最后是waitFiveSeconds函數(shù)

在同步任務(wù)執(zhí)行的期間,‘timera’,‘timerb’對(duì)應(yīng)的回調(diào)和click事件的回調(diào)先后入隊(duì)列。

同步任務(wù)結(jié)束后,js引擎線程空閑后會(huì)線查看是否有事件可執(zhí)行,接著在處理其他異步任務(wù),因此會(huì)有下面的輸出:

0
1
2
3
4
click begin
finished waiting
2 click  //5s中兩次點(diǎn)擊
timer a
timer b
2 click  //5s后兩次點(diǎn)擊

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

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

相關(guān)文章

  • 前端面試:js同步異步問(wèn)題

    摘要:今天的已經(jīng)成為一門功能全面的編程語(yǔ)言總結(jié)最初的用途是為來(lái)實(shí)現(xiàn)用戶與瀏覽器的交互二為何是單線程的的單線程,與它的用途有關(guān)。這決定了它只能是單線程,否則會(huì)帶來(lái)很復(fù)雜的同步問(wèn)題。 showImg(https://user-gold-cdn.xitu.io/2019/3/31/169d1c40c27a173c?w=428&h=252&f=png&s=35393); 前言 我本來(lái)是打算寫一篇co...

    call_me_R 評(píng)論0 收藏0
  • 淺析JavaScript異步

    摘要:回調(diào)函數(shù),一般在同步情境下是最后執(zhí)行的,而在異步情境下有可能不執(zhí)行,因?yàn)槭录](méi)有被觸發(fā)或者條件不滿足。同步方式請(qǐng)求異步同步請(qǐng)求當(dāng)請(qǐng)求開始發(fā)送時(shí),瀏覽器事件線程通知主線程,讓線程發(fā)送數(shù)據(jù)請(qǐng)求,主線程收到 一直以來(lái)都知道JavaScript是一門單線程語(yǔ)言,在筆試過(guò)程中不斷的遇到一些輸出結(jié)果的問(wèn)題,考量的是對(duì)異步編程掌握情況。一般被問(wèn)到異步的時(shí)候腦子里第一反應(yīng)就是Ajax,setTimse...

    Tangpj 評(píng)論0 收藏0
  • JavaScript系列——JavaScript同步異步、回調(diào)執(zhí)行順序之經(jīng)典閉包setTimeou

    摘要:同步異步回調(diào)傻傻分不清楚。分割線上面主要講了同步和回調(diào)執(zhí)行順序的問(wèn)題,接著我就舉一個(gè)包含同步異步回調(diào)的例子。同步優(yōu)先回調(diào)內(nèi)部有個(gè),第二個(gè)是一個(gè)回調(diào)回調(diào)墊底。異步也,輪到回調(diào)的孩子們回調(diào),出來(lái)執(zhí)行了。 同步、異步、回調(diào)?傻傻分不清楚。 大家注意了,教大家一道口訣: 同步優(yōu)先、異步靠邊、回調(diào)墊底(讀起來(lái)不順) 用公式表達(dá)就是: 同步 => 異步 => 回調(diào) 這口訣有什么用呢?用來(lái)對(duì)付面試的...

    lewif 評(píng)論0 收藏0
  • JavaScript系列——JavaScript同步異步、回調(diào)執(zhí)行順序之經(jīng)典閉包setTimeou

    摘要:同步異步回調(diào)傻傻分不清楚。分割線上面主要講了同步和回調(diào)執(zhí)行順序的問(wèn)題,接著我就舉一個(gè)包含同步異步回調(diào)的例子。同步優(yōu)先回調(diào)內(nèi)部有個(gè),第二個(gè)是一個(gè)回調(diào)回調(diào)墊底。異步也,輪到回調(diào)的孩子們回調(diào),出來(lái)執(zhí)行了。 同步、異步、回調(diào)?傻傻分不清楚。 大家注意了,教大家一道口訣: 同步優(yōu)先、異步靠邊、回調(diào)墊底(讀起來(lái)不順) 用公式表達(dá)就是: 同步 => 異步 => 回調(diào) 這口訣有什么用呢?用來(lái)對(duì)付面試的...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<