同步方式: 代碼是順序執行的,而且發送請求的時候界面會阻塞。CPU按順序執行,前一個任務結束,再執行下一個任務.javascript
異步模式: 界面不會阻塞,主線程會當即返回,等到異步請求完成的時候再從線程池中取一個線程處理。CPU跳過等待時間長的任務,先處理後面的任務.java
[1] JavaScript運行瀏覽器
JavaScript引擎是單線程運行的,瀏覽器不管在何時都只且只有一個線程在運行JavaScript程序.瀏覽器的內核是多線程的,它們在內核制控下相互配合以保持同步,一個瀏覽器至少實現三個常駐線程:javascript引擎線程,GUI渲染線程,瀏覽器事件觸發線程。這些異步線程都會產生不一樣的異步的事件.數據結構
1. javascript引擎是基於事件驅動單線程執行的,JS引擎一直等待着任務隊列中任務的到來,而後加以處理,瀏覽器不管何時都只有一個JS線程在運行JS程序。多線程
2. GUI渲染線程負責渲染瀏覽器界面,當界面須要重繪(Repaint)或因爲某種操做引起迴流(reflow)時,該線程就會執行。但須要注意 GUI渲染線程與JS引擎是互斥的,當JS引擎執行時GUI線程會被掛起,GUI更新會被保存在一個隊列中等到JS引擎空閒時當即被執行。異步
3. 事件觸發線程,當一個事件被觸發時該線程會把事件添加到待處理隊列的隊尾,等待JS引擎的處理。這些事件可來自JavaScript引擎當前執行的代碼塊如setTimeOut、也可來自瀏覽器內核的其餘線程如鼠標點擊、AJAX異步請求等,但因爲JS的單線程關係全部這些事件都得排隊等待JS引擎處理。(當線程中沒有執行任何同步代碼的前提下才會執行異步代碼)函數
[2] JavaScript運行機制oop
程序中跑兩個線程,一個負責程序自己的運行,做爲主線程; 另外一個負責主線程與其餘線程的的通訊,被稱爲「Event Loop 線程" 。每當遇到異步任務,交給 EventLoop 線程,而後本身日後運行,等到主線程運行完後,再去 EventLoop 線程拿結果。線程
1)全部任務都在主線程上執行,造成一個執行棧(execution context stack)。blog
2)主線程以外,還存在一個"任務隊列"(task queue)。系統把異步任務放到"任務隊列"之中,而後繼續執行後續的任務。
3)一旦"執行棧"中的全部任務執行完畢,系統就會讀取"任務隊列"。若是這個時候,異步任務已經結束了等待狀態,就會從"任務隊列"進入執行棧,恢復執行。
4)主線程不斷重複上面的第三步。
"回調函數"(callback),就是那些會被主線程掛起來的代碼。異步任務必須指定回調函數,當異步任務從"任務隊列"回到執行棧,回調函數就會執行。"任務隊列"是一個先進先出的數據結構,排在前面的事件,優先返回主線程。主線程的讀取過程基本上是自動的,只要執行棧一清空,"任務隊列"上第一位的事件就自動返回主線程。
Event Loop(事件循環): 主線程從"任務隊列"中讀取事件,這個過程是循環不斷的,因此整個的這種運行機制又稱爲Event Loop。
Event Loop 是一個很重要的概念,指的是計算機系統的一種運行機制。
JavaScript語言就採用這種機制,來解決單線程運行帶來的一些問題。
[3] 異步setTimeout & setInterval
setTimeout:在指定的毫秒數後,將定時任務處理的函數添加到執行隊列的隊尾。
setInterval:按照指定的週期(以毫秒數計時),將定時任務處理函數添加到執行隊列的隊尾。
從主線程的角度看,一個異步過程包括下面兩個要素:
發起函數(或叫註冊函數)A
回調函數callbackFn
它們都是在主線程上調用的,其中註冊函數用來發起異步過程,回調函數用來處理結果。
setTimeout(fn, 1000);
其中的setTimeout就是異步過程的發起函數,fn是回調函數。
用一句話歸納:工做線程將消息放到消息隊列,主線程經過事件循環過程去取消息。
消息隊列:消息隊列是一個先進先出的隊列,它裏面存放着各類消息。
事件循環:事件循環是指主線程重複從消息隊列中取消息、執行的過程。