更新時間:2021年06月17日14時20分 來源:傳智教育 瀏覽次數(shù):
JavaScript的定時器可以完成一些異步操作。例如,同時設(shè)置多個定時器,每個定時器都在3秒后執(zhí)行一段代碼,則3秒后,這些定時器中的代碼都會執(zhí)行。JavaScript的定時器雖然沒有Java中的多線程那樣強大,但在開發(fā)中也能滿足大部分的需求。下面針對JavaSeript的執(zhí)行機制進行講解。
1、單線程
JavaScript語言的一大特點就是單線程,也就是說,同-一個時間只能做一件事。這是因為JavaScript這門腳本語言誕生的使命所致,即JavaScript是為處理頁面中用戶的交互,以及操作DOM而誕生的。比如,對某個DOM元素進行添加和刪除操作,不能同時進行,應(yīng)該先進行添加,之后再刪除。
單線程就意味著,所有任務(wù)需要排隊,前一個任務(wù)結(jié)束,才會執(zhí)行后一個任務(wù),這樣所導(dǎo)致的問題是,如果JavaScript執(zhí)行的時間過長,就會造成頁面的渲染不連貫,導(dǎo)致頁面渲染加載有阻塞的感覺。 為了更好地理解,下面我們通過段代碼來演示。
console.log(1); setTimeout(function () { console.log(3); }, 5000); console.log(2);
執(zhí)行上述代碼,在控制臺會看到程序先輸出了1、2,等待5秒后輸出3。由此可見,當(dāng)調(diào)用setTimeout()方法后,該方法會立即執(zhí)行完成,然后執(zhí)行后面的代碼,在控制臺中輸出2。而為setTimeout()傳入的函數(shù),它會在5秒后執(zhí)行。像這樣的操作就稱為異步操作。這個異步執(zhí)行的函數(shù)稱為回調(diào)函數(shù),它的調(diào)用時機是由定時器來決定的。
2、同步和異步
為了更好地利用多核CPU的計算能力,HTML5提出Web Worker標(biāo)準(zhǔn),允許JavaScript腳本創(chuàng)建多個線程。于是JavaScript出現(xiàn)了同步和異步的概念。
所謂同步,就是前一個任務(wù)結(jié)束后再執(zhí)行后一個任務(wù),程序的執(zhí)行順序與任務(wù)的排列順序是一致的、同步的。比如做飯的同步做法,燒水煮飯,等水開了之后,再去切菜,炒菜。
所謂異步,就是在做一件事件的同時,可以去處理其他的事情。還以做飯為例,異步做法是,在燒水煮飯的同時去切菜炒菜。 同步任務(wù)都是在主線程上執(zhí)行的,會形成一個執(zhí)行棧,而異步任務(wù)是通過回調(diào)函數(shù)實現(xiàn)的。一般來說,異步任務(wù)有3種類型,第1種是普通事件,如click、resize 等;第2種是資源加載,如load、error等;第3種是定時器,如setInterval()、setTimeout()。
3、執(zhí)行機制
當(dāng)定時器的時間設(shè)為0的時候,就會產(chǎn)生一個問題, 到底是為定時器傳入的回調(diào)函數(shù)優(yōu)先執(zhí)行,還是setTimeout()后面的代碼優(yōu)先執(zhí)行呢?示例代碼如下。
console.log(1); setTimeout (function () { console.log(3); }, 0); for (var i = 0, str = ''; i< 900000; i++) { str += i; //利用字符串拼接運算拖慢執(zhí)行時間 } console.log(2);
上述代碼執(zhí)行后,輸出順序為1、2、3。顯然,為定時器傳入的回調(diào)函數(shù)是最后執(zhí)行的。為了降低偶然性,第5 ~ 7行的代碼拖慢了執(zhí)行時間,但最終結(jié)果仍然是3最后輸出。 在JavaScript中,同步任務(wù)是優(yōu)先執(zhí)行的,它們會被放入執(zhí)行棧中執(zhí)行,而異步任務(wù)(回調(diào)函數(shù))則被放人任務(wù)隊列中,如下圖所示。
在上圖中,一且執(zhí)行棧中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會按次序讀取任務(wù)隊列中的異步任務(wù),于是被讀取的異步任務(wù)就會結(jié)束等待狀態(tài),進入執(zhí)行棧,開始執(zhí)行。因為JavaScript的主線程會不斷地重復(fù)獲得任務(wù)、執(zhí)行任務(wù)、再獲取任務(wù)、再執(zhí)行,所以這種機制被稱為事件循環(huán)( Event Loop )。
猜你喜歡: