在瀏覽器中,事件做爲一個極爲重要的機制,給予JavaScript響應用戶操做與DOM變化的能力。在NodeJS中。異步事件驅動模型則是提升併發能力的基礎。javascript
操做系統處理鍵盤等硬件輸入就是經過中斷來進行的。這個方式的優勢是即便沒有多線程,咱們也可以放心地運行咱們的代碼,CPU收到中斷信號以後本身主動地轉去運行對應的中斷處理程序,處理完畢後會恢復原來的代碼的運行環境繼續運行。java
這樣的方式需要硬件的支持。通常來講都會被操做系統封裝起來。瀏覽器
輪詢方式的一個缺點就是:假設在主線程的消息循環裏進行耗時操做。程序就沒法及時響應新的消息。多線程
不論是Node仍是瀏覽器中,都有setTimeout和setInterval這兩個定時器函數。並且其工做特色基本一樣。併發
JavaScript中的定時器並不一樣於計算機底層的定時中斷。異步
中斷到來時,當前運行代碼會被打斷。轉去運行定時中斷處理函數。函數
而JavaScript的定時器到時,假設當前運行線程沒有正在運行的代碼。則運行對應的回調函數;假設當前有代碼在運行中,JavaScript引擎既不會中斷當前代碼轉去運行回調,也不會開新的線程運行回調,而是當前代碼運行完成以後纔去處理。高併發
console.time("setTimoutLabel"); //標記時間開始 setTimeout(function() { console.timeEnd("setTimoutLabel"); //標記時間結束 }, 100); for (var i = 0; i < 100000; i++) { }
運行上面的代碼。可以看到終於輸出的時間並不是100ms左右,而是數秒。post
這說明在循環完畢以前,定時回調函數確實沒有被運行。而是推遲到了循環結束。實際上在JavaScript代碼運行中,全部的事件都沒法獲得處理,必須等到當前代碼全部完畢,才幹去處理新的事件。這就是爲何在瀏覽器中運行耗時JavaScript代碼時,瀏覽器會失去響應。spa
1. javascript引擎僅僅有一個線程,迫使異步事件僅僅能增長隊列去等待運行。
2. 在運行異步代碼的時候,假設定時器被正在運行的代碼堵塞了,它將會進入隊列的尾部去等待運行直到下一次可能運行的時間出現(可能超過設定的延時時間)。setTimeout 和setInterval 是有着本質差異的:setTimeout 這段代碼會在每次回調函數運行以後至少需要延時「指定延遲毫秒值」再去執行(多是不少其它,但是不會少)。但是setInterval會每隔「指定延遲毫秒值」就去嘗試運行一次回調函數。不管上一個回調函數是否是還在運行。