天天看點

JavaScript有同步任務和異步任務,浏覽器是怎麼處理的?

1.在讨論浏覽器與JavaScript之前,我們先來簡單了解一下程序與線程

程序(process):資源配置設定的最小機關

程序是應用程式的執行執行個體,是作業系統進行資源配置設定和排程的一個獨立機關。

線程(thread):CPU排程的最小機關

線程是程序内部的一個執行單元,是被系統獨立排程和分派的基本機關。系統建立好程序後,實際上就啟動執行了該程序的主執行線程。

上面這樣講可能不是很容易了解,我們以工廠🏭模式來比喻:

  • 計算機的核心是CPU,它承擔了所有的計算任務。它就像一座工廠🏭,時刻在運作着。
  • 單個CPU一次隻能運作一個任務
  • 程序就好比工廠的工廠中的房間🚗,它代表CPU所能處理的單個任務
  • 一個工廠中的房間裡,可以有很多勞工👷。他們協同完成一個任務
  • 線程就好比工廠中的房間裡的勞工👷,一個程序可以包含多個線程
2.浏覽器多線程與Javascript單線程(單線程與多線程)

首先浏覽器是多線程的,是以浏覽器一次能夠處理多個事件,比如渲染頁面,腳本執行,事件處理等。

JavaScript

是單線程的(浏覽器隻給JS配置設定了一個線程)

JavaScript單線程

單線程的特點就是一次隻能處理一件事情。後一個任務需要等待前一個任務執行完再執行。

JS在單線程中實作異步機制隻要依靠浏覽器的

任務隊列

,任務隊列分為

同步任務隊列

異步任務隊列

,異步任務又可以分為

宏任務

微任務

在同步任務自上而下執行時,如果遇到一個異步任務,不會立即執行,而是把它放到異步任務隊列中去排隊,當同步任務執行完成後,才會到異步任務隊列進行查找等待任務隊列中的内容(同步任務隊列完不成,不管異步任務是否達到時間,都不執行),等達到條件後執行,然後再接着去異步任務隊列中 查找。這就是因為js是單線程的,一次隻能處理一件事情

JavaScript為什麼要設計成單線程

JavaScript

之是以采用單線程,而不是多線程,跟它的曆史有關。最開始的JavaScript功能并沒有現在這麼強大,作為浏覽器腳本語言,它最初主要是用來處理頁面的

使用者互動

,以及

DOM的操作

。如果

JavaScript

是多線程的話,假設存在兩個線程同時操作一個DOM,這時候浏覽器就不知道應該處理哪個線程的操作結果了。

3.同步與異步任務

**同步: ** 在一個線程上同一時間隻能做一件事情,當情事情做完才能進行下一個任務。

異步: 在主棧中執行一個任務,但是發現這個任務是一個異步的操作,會将它放到異步任務隊列中。

異步任務又分為宏任務與微任務:

宏任務:定時器

setTimeout

setInterval

事件綁定

回調函數

node中的fs子產品

微任務:

new Promise().then(回調)

process.nextTick()

async await

4.執行棧與任務隊列

1)執行棧:從名字可以看出,執行棧使用到的是資料結構中的棧結構, 它是一個存儲函數調用的棧結構,遵循先進後出的原則。它主要負責跟蹤所有要執行的代碼。 每當一個函數執行完成時,就會從堆棧中彈出(pop)該執行完成函數;如果有代碼需要進去執行的話,就進行 push 操作。

2)任務隊列: 從名字中可以看出,任務隊列使用到的是資料結構中的隊列結構,它用來儲存異步任務,遵循先進先出的原則。它主要負責将新的任務發送到隊列中進行處理。

執行順序:

JavaScript在執行代碼時,會将同步的代碼按照順序排在執行棧中,然後依次執行裡面的函數。當遇到異步任務時,就将其放入任務隊列中,等待目前執行棧所有同步代碼執行完成之後,就會從異步任務隊列中取出已完成的異步任務的回調并将其放入執行棧中繼續執行,如此循環往複,直到執行完所有任務

先執行同步任務,執行完接着執行微任務,最後執行宏任務。這個過程會不斷重複

JavaScript有同步任務和異步任務,浏覽器是怎麼處理的?
下面看幾道經典面試題
console.log("script start");

async function async1() {
  await async2();
  console.log("async1 end");
}

async function async2() {
  console.log("async2 end");
}

async1();

setTimeout(function () {
  console.log("setTimeout");
}, 0);

new Promise((resolve) => {
  console.log("Promise");
  resolve();
})
  .then(function () {
    console.log("promise1");
  })
  .then(function () {
    console.log("promise2");
  });

console.log("script end");
// script start => async2 end => Promise => script end => async1 end=> promise1 => promise2 => setTimeout

           

解析:

1.首先執行同步任務:列印script start,async2 end,Promise,script end

2.同步任務執行完,開始執行微任務:async1 end,promise1,promise2

3.最後執行宏任務:setTimeout

作者:前端南玖

出處:https://www.cnblogs.com/songyao666/

-------------------------------------------

個性簽名:智者創造機會,強者把握機會,弱者坐等機會。做一個靈魂有趣的人!

如果覺得這篇文章對你有小小的幫助的話,可以關注下方公衆号,可以超前閱讀筆者的文章,謝謝~

歡迎加入前端技術交流群:928029210

JavaScript有同步任務和異步任務,浏覽器是怎麼處理的?

繼續閱讀