所謂單線程,就是只一次只能完成一件任務(wù)。如果有多個(gè)任務(wù),就必須排隊(duì),前面一個(gè)任務(wù)完成,在執(zhí)行后面一個(gè)任務(wù),以次類(lèi)推。
js執(zhí)行分為同步和異步,其中異步來(lái)自于瀏覽器提供的異步隊(duì)列,在瀏覽器中分為兩個(gè)任務(wù)隊(duì)列,一個(gè)是主任務(wù)隊(duì)列【同步編程】,一個(gè)是等待任務(wù)隊(duì)列【異步編程】
一個(gè)瀏覽器通常由一下幾個(gè)常住的線程
setTimeout
,setInterval
注意:渲染線程和js引擎線程是不能同時(shí)進(jìn)行的。渲染線程在執(zhí)行任務(wù)的時(shí)候,js引擎線程會(huì)被掛起。因?yàn)閖s可以操作DOM,若在渲染中js處理了DOM,瀏覽器可能就不知所措了
雖然JavaScript是單線程的,可是瀏覽器內(nèi)部不是單線程的。一些I/O操作、定時(shí)器的計(jì)時(shí)和事件監(jiān)聽(tīng)(click, keydown...)等都是由瀏覽器提供的其他線程來(lái)完成的。
"同步模式"就是上一段的模式,后一個(gè)任務(wù)等待前一個(gè)任務(wù)結(jié)束,然后再執(zhí)行,程序的執(zhí)行順序與任務(wù)的排列順序是一致的、同步的;"異步模式"則完全不同,每一個(gè)任務(wù)有一個(gè)或多個(gè)回調(diào)函數(shù)(callback),前一個(gè)任務(wù)結(jié)束后,不是執(zhí)行后一個(gè)任務(wù),而是執(zhí)行回調(diào)函數(shù),后一個(gè)任務(wù)則是不等前一個(gè)任務(wù)結(jié)束就執(zhí)行,所以程序的執(zhí)行順序與任務(wù)的排列順序是不一致的、異步的。
"異步模式"非常重要。在瀏覽器端,耗時(shí)很長(zhǎng)的操作都應(yīng)該異步執(zhí)行,避免瀏覽器失去響應(yīng),最好的例子就是Ajax操作。在服務(wù)器端,"異步模式"甚至是唯一的模式,因?yàn)閳?zhí)行環(huán)境是單線程的,如果允許同步執(zhí)行所有http請(qǐng)求,服務(wù)器性能會(huì)急劇下降,很快就會(huì)失去響應(yīng)。
console.log(1) function fn(){ console.log(2) } fn() console.log(3)
上面代碼輸入1 2 3 ,因?yàn)閖s是單線程的,代碼由上而下依次執(zhí)行
js中
回調(diào)函數(shù)
上面這4中都是屬于異步的
console.log(1) setTimeout(()=>{ console.log(2) }) console.log(3)
上面代碼執(zhí)行會(huì)輸出,1 3 2 ,因?yàn)?code>setTimeout是異步的,js會(huì)將
setTimeout
放到異步隊(duì)列,等待同步隊(duì)列全部執(zhí)行完畢,在執(zhí)行異步隊(duì)列
js中有兩類(lèi)任務(wù)隊(duì)列:宏任務(wù)隊(duì)列和微任務(wù)隊(duì)列。宏任務(wù)隊(duì)列可以有多個(gè),微任務(wù)隊(duì)列只有一個(gè)
setTimeout(_ => console.log(4))new Promise(resolve => { resolve() console.log(1)}).then(_ => { console.log(3)})console.log(2)
上面代碼中,setTimeout就是作為宏任務(wù)來(lái)存在的,而Promise.then則是具有代表性的微任務(wù)
所有會(huì)進(jìn)入的異步都是指的事件回調(diào)中的那部分代碼
來(lái)源:http://www.icode9.com/content-4-204251.html也就是說(shuō)
new Promise
在實(shí)例化的過(guò)程中所執(zhí)行的代碼都是同步進(jìn)行的,而then
中注冊(cè)的回調(diào)才是異步執(zhí)行的。
在同步代碼執(zhí)行完成后才回去檢查是否有異步任務(wù)完成,并執(zhí)行對(duì)應(yīng)的回調(diào),而微任務(wù)又會(huì)在宏任務(wù)之前執(zhí)行。所以就得到了上面的輸出1 2 3 4
聯(lián)系客服