首先火本,js是單線程的钙畔,這一點(diǎn)毋庸置疑。
同步異步的概念:
同步:大家按照順序揍魂,你運(yùn)行完我運(yùn)行现斋,不存在你我同時(shí)運(yùn)行的情況庄蹋;優(yōu)點(diǎn)是實(shí)現(xiàn)起來(lái)比較簡(jiǎn)單遂鹊,執(zhí)行環(huán)境相對(duì)單純秉扑;壞處是一旦出現(xiàn)耗時(shí)操作就會(huì)導(dǎo)致整個(gè)程序癱瘓舟陆,停止運(yùn)行;
異步:大家齊頭并進(jìn)踱承,一起運(yùn)行茎活,也就是明面上的“多線程”载荔;
既然異步就約等于多線程,那js這樣一個(gè)單線程語(yǔ)言中工扎,怎么會(huì)存在異步呢定庵?其實(shí)實(shí)際上js確實(shí)不存在真正意義上的“異步”,而是使用 events loop
來(lái)實(shí)現(xiàn)類似異步的效果。events loop
實(shí)際上就是在js在主要代碼(也就是在html中所有定義的script
標(biāo)簽)運(yùn)行完后蓝仲,會(huì)開啟的一個(gè)循環(huán)袱结,主要用于監(jiān)聽 HTML 事件和執(zhí)行異步操作溢吻。所以實(shí)際上js就是單線程的促王,包括setTimeout
蝇狼,setInterval
,XMLHttpRequest
都是如此的操作:將需要執(zhí)行的耗時(shí)操作放入循環(huán)中颤专,并在恰當(dāng)實(shí)際執(zhí)行回調(diào)函數(shù)血公。
我們可以用以下代碼來(lái)測(cè)試js一定是單線程:
setTImeout(function(){
alert("我是一個(gè)彈窗");
},1000);
while(true){
//不會(huì)結(jié)束的死循環(huán)
}
js有多種方法來(lái)實(shí)現(xiàn)偽異步,比如:回調(diào)函數(shù)垦写,事件監(jiān)聽梯投,發(fā)布訂閱分蓖,Promises對(duì)象么鹤。
回調(diào)函數(shù)就是上述的setTimeout
蒸甜,setInterval
窍荧,XMLHttpRequest
所使用的方法蕊退,傳入一個(gè)函數(shù),并在耗時(shí)操作完成時(shí)執(zhí)行茉贡。
事件監(jiān)聽就是設(shè)定幾個(gè)事件腔丧,為其設(shè)置監(jiān)聽事件愉粤,當(dāng)某個(gè)事件發(fā)生時(shí),執(zhí)行對(duì)應(yīng)的函數(shù)影暴。
發(fā)布訂閱這個(gè)模式與安卓中的廣播類似型宙,可以通過(guò)一個(gè)“平臺(tái)”來(lái)“發(fā)布”某些信息妆兑,之后會(huì)將這個(gè)調(diào)用所有“訂閱”這個(gè)信息的函數(shù),與事件監(jiān)聽很像腺逛,但是可以通過(guò)從消息中心(其實(shí)就是)查看來(lái)更好的監(jiān)控程序屉来。
Promises函數(shù),每一個(gè)異步任務(wù)返回一個(gè)Promise對(duì)象慨绳,該對(duì)象有一個(gè)then方法脐雪,允許指定回調(diào)函數(shù),會(huì)在上一個(gè)世界結(jié)束后調(diào)用脂信。(詳細(xì)可以查看菜鳥教程等)
其實(shí)看完你會(huì)發(fā)現(xiàn)狰闪,所有在js中的“異步”操作,都是耗時(shí)操作加入事件循環(huán)丽声,并在特定時(shí)機(jī)執(zhí)行一個(gè)函數(shù)的模式恒序。
原文鏈接