所有的任務(wù)分為兩種,一種是同步任務(wù),一種是異步任務(wù)。 同步任務(wù)指的是,在主線程上排隊(duì)執(zhí)行的任務(wù),只有前一個任務(wù)執(zhí)行完畢,才能執(zhí)行后一個任務(wù); (1)所有同步任務(wù)都在主線程上執(zhí)行,形成一個執(zhí)行棧(execution context stack)。 setTimeOut函數(shù)為異步任務(wù),for循環(huán)為同步任務(wù),setTimeOut里的函數(shù)為回調(diào)函數(shù)。執(zhí)行順序?yàn)椋和絻?yōu)先,異步靠邊,回調(diào)墊底。所以即使setTimeOut的時間參數(shù)是0依然會放到任務(wù)隊(duì)列里,而不是主線程。主線程執(zhí)行完for循環(huán)以后才執(zhí)行異步任務(wù)setTimeOut。另外setTimeout()只是將事件插入了"任務(wù)隊(duì)列",必須等到當(dāng)前代碼(執(zhí)行棧)執(zhí)行完,主線程才會去執(zhí)行它指定的回調(diào)函數(shù)。要是當(dāng)前代碼耗時很長,有可能要等很久,所以并沒有辦法保證,回調(diào)函數(shù)一定會在setTimeout()指定的時間執(zhí)行。 javascript是單線程。單線程就意味著,所有任務(wù)需要排隊(duì),前一個任務(wù)結(jié)束,才會執(zhí)行后一個任務(wù)。如果前一個任務(wù)耗時很長,后一個任務(wù)就不得不一直等著。于是就有一個概念——任務(wù)隊(duì)列。如果排隊(duì)是因?yàn)橛?jì)算量大,CPU忙不過來,倒也算了,但是很多時候CPU是閑著的,因?yàn)镮O設(shè)備(輸入輸出設(shè)備)很慢(比如Ajax操作從網(wǎng)絡(luò)讀取數(shù)據(jù)),不得不等著結(jié)果出來,再往下執(zhí)行。于是JavaScript語言的設(shè)計(jì)者意識到,這時主線程完全可以不管IO設(shè)備,掛起處于等待中的任務(wù),先運(yùn)行排在后面的任務(wù)。等到IO設(shè)備返回了結(jié)果,再回過頭,把掛起的任務(wù)繼續(xù)執(zhí)行下去。 ? JavaScript的單線程,與它的用途有關(guān)。作為瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操作DOM。這決定了它只能是單線程,否則會帶來很復(fù)雜的同步問題。比如,假定JavaScript同時有兩個線程,一個線程在某個DOM節(jié)點(diǎn)上添加內(nèi)容,另一個線程刪除了這個節(jié)點(diǎn),這時瀏覽器應(yīng)該以哪個線程為準(zhǔn)? 所以,為了避免復(fù)雜性,從一誕生,JavaScript就是單線程,這已經(jīng)成這門語言的核心特征,將來也不會改變。 注:所謂單線程,是指在JS引擎中負(fù)責(zé)解釋和執(zhí)行JavaScript代碼的線程只有一個。 總結(jié):計(jì)算機(jī)中的同步就是排隊(duì)等待,假如你是第一百零一個備胎,那你只能等前面的一百個爆了之后才能‘處理'你。異步就是,盡管你是第一百零一個,她還是能照顧到你的感受。
?例: 也就是說,setTimeout里的函數(shù)并沒有立即執(zhí)行,而是延遲了一段時間,滿足一定條件后,才去執(zhí)行的,這類代碼,我們叫異步代碼。 總結(jié):同步可以保證順序一致,但是容易導(dǎo)致阻塞;異步可以解決阻塞問題,但是會改變順序性,根據(jù)不同的需要去寫你的代碼。 Promise是異步的,是指他的then()和catch()方法,Promise本身還是同步的,所以這里先執(zhí)行a變量內(nèi)部的Promise同步代碼。(同步優(yōu)先) 注意? 同步(Promise)>異步(微任務(wù)(process.nextTick ,Promises.then, Promise.catch ,resove,reject,MutationObserver)>宏認(rèn)為(setTimeout,setInterval,setImmediate)) process.nextTick> Promises.then 同步代碼執(zhí)行完成后,才會再去執(zhí)行異步,哪怕異步已經(jīng)到了執(zhí)行的時間了。 JavaScript的任務(wù)分為微任務(wù)(Microtasks)和宏任務(wù)(task);
[宏任務(wù):macro?task] ????????- 定時器 ????????-?事件綁定 ????????-?ajax ????????-?回調(diào)函數(shù) ????????-?Node中fs可以進(jìn)行異步的I/O操作 [微任務(wù):micro?task] ????????-?Promise(async/await)??=>?Promise并不是完全的同步,當(dāng)在Excutor中執(zhí)行resolve或者reject的時候,此時是異步操作,會先執(zhí)行then/catch等,當(dāng)主棧完成后,才會再去調(diào)用resolve/reject把存放的方法執(zhí)行 ????????-?process.nextTick (node中實(shí)現(xiàn)的api,把當(dāng)前任務(wù)放到主棧最后執(zhí)行,當(dāng)主棧執(zhí)行完,先執(zhí)行nextTick,再到等待隊(duì)列中找) -?MutationObserver? ?(創(chuàng)建并返回一個新的?MutationObserver?它會在指定的DOM發(fā)生變化時被調(diào)用。) 任務(wù)隊(duì)列到達(dá)時間后先進(jìn)先出的原則 ? 參考: 1:https://blog.csdn.net/qq_40959677/article/details/95961443 ? ![]() ![]() |
|