91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

實例分析js事件循環機制

發布時間:2020-10-15 16:51:22 來源:腳本之家 閱讀:112 作者:laozhang 欄目:web開發

本文通過實例給大家詳細分析了JS中事件循環機制的原理和用法,以下是全部內容:

var start = new Date()
setTimeout(function () {
 var end = new Date
 console.log('Time elapsed:', end - start, 'ms')
}, 500)
while (new Date() - start < 1000) {
}

有其他語言能完成預期的功能嗎?Java, 在Java.util.Timer中,對于定時任務的解決方案是通過多線程手段實現的,任務對象存儲在任務隊列,由專門的調度線程,在新的子線程中完成任務的執行

js是單線程的

JavaScript的主要用途是與用戶互動,以及操作DOM。這決定了它只能是單線程,否則會帶來很復雜的同步問題。

為了利用多核CPU的計算能力,HTML5提出Web Worker標準,允許JavaScript腳本創建多個線程,但是子線程完全受主線程控制,且不得操作DOM。所以,這個新標準并沒有改變JavaScript單線程的本質。

函數調用棧和任務隊列

實例分析js事件循環機制

調用棧

JS執行時會形成調用棧,調用一個函數時,返回地址、參數、本地變量都會被推入棧中,如果當前正在運行的函數中調用另外一個函數,則該函數相關內容也會被推入棧頂.該函數執行完畢,則會被彈出調用棧.變量也隨之彈出,由于復雜類型值存放于堆中,因此彈出的只是指針,他們的值依然在堆中,由GC決定回收.

事件循環(event loop) & 任務隊列(task queue)

JavaScript 主線程擁有一個執行棧以及一個任務隊列

遇到異步操作(例如:setTimeout, AJAX)時,異步操作會由瀏覽器(OS)執行,瀏覽器會在這些任務完成后,將事先定義的回調函數推入主線程的任務隊列(task queue)中,當主線程的執行棧清空之后會讀取task queue中的回調函數,當task queue被讀取完畢之后,主線程接著執行,從而進入一個無限的循環,這就是事件循環.

主線程執行棧 & 任務隊列 循環執行,構成事件循環

結論

setTimeout()只是將事件插入了"任務隊列",必須等到當前代碼(執行棧)執行完,主線程才會去執行它指定的回調函數。要是當前代碼耗時很長,有可能要等很久,所以并沒有辦法保證,回調函數一定會在setTimeout()指定的時間執行。

另一個例子

(function test() {
 setTimeout(function() {console.log(4)}, 0);
 new Promise(function executor(resolve) {
 console.log(1);
 for( var i=0 ; i<10000 ; i++ ) {
 i == 9999 && resolve();
 }
 console.log(2);
 }).then(function() {
 console.log(5);
 });
 console.log(3);
})()

Macrotask & Microtask

macrotask 和 microtask 是異步任務的兩種分類。在掛起任務時,JS 引擎會將所有任務按照類別分到這兩個隊列中,首先在 macrotask 的隊列(這個隊列也被叫做 task queue)中取出第一個任務,執行完畢后取出 microtask 隊列中的所有任務順序執行;之后再取 macrotask 任務,周而復始,直至兩個隊列的任務都取完。

macro-task: script(整體代碼), setTimeout, setInterval, setImmediate, I/O, UI rendering
micro-task: process.nextTick, Promises(這里指瀏覽器實現的原生 Promise), Object.observe, MutationObserver

實例分析js事件循環機制

結論

全部代碼(script) macrotask -> microtask queue (含有promise.then) -> macrotask(setTimeout) -> 下一個microtask

Node.js的事件循環

process.nextTick & setImmediate

process.nextTick指定的任務總是發生在所有異步任務之前

setImmediate指定的任務總是在下一次Event Loop時執行

process.nextTick(function A() {
 console.log(1);
 process.nextTick(function B(){console.log(2);});
});
setTimeout(function timeout() {
 console.log('TIMEOUT FIRED');
}, 0)
new Promise(function(resolve) {
 console.log('glob1_promise');
 resolve();
}).then(function() {
 console.log('glob1_then')
})
process.nextTick(function() {
 console.log('glob1_nextTick');
})
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

合肥市| 衡阳县| 黑河市| 衡水市| 乐亭县| 彰化县| 德令哈市| 宜丰县| 保康县| 喜德县| 固安县| 贵州省| 即墨市| 绍兴市| 龙门县| 池州市| 明星| 樟树市| 邵阳县| 宁河县| 义马市| 陵川县| 鹤壁市| 山东省| 普定县| 新民市| 太康县| 永清县| 黔江区| 平定县| 郸城县| 隆化县| 嘉黎县| 伽师县| 松溪县| 金坛市| 从化市| 铁岭县| 古蔺县| 龙南县| 武安市|