js中同步異步,任務隊列


單線程

  • 瀏覽器是多線程運行的,它給js分配一個線程;js就是單線程運行的【一次只干一件事】

所謂單線程,就是只一次只能完成一件任務。如果有多個任務,就必須排隊,前面一個任務完成,在執行后面一個任務,以次類推。

js執行分為同步和異步,其中異步來自於瀏覽器提供的異步隊列,在瀏覽器中分為兩個任務隊列,一個是主任務隊列【同步編程】,一個是等待任務隊列【異步編程】

了解js的異步我們應該先了解下js的運行環境=>瀏覽器

一個瀏覽器通常由一下幾個常住的線程

  • 渲染引擎線程:顧名思義,該線程負責頁面的渲染
  • js引擎線程:負責js解析和執行
  • 定時觸發器線程:處理定時事件,比如setTimeout,setInterval
  • 事件觸發線程:處理DOM事件
  • 異步http請求線程:處理http請求

注意:渲染線程和js引擎線程是不能同時進行的。渲染線程在執行任務的時候,js引擎線程會被掛起。因為js可以操作DOM,若在渲染中js處理了DOM,瀏覽器可能就不知所措了

雖然JavaScript是單線程的,可是瀏覽器內部不是單線程的。一些I/O操作、定時器的計時和事件監聽(click, keydown...)等都是由瀏覽器提供的其他線程來完成的。

Javascript語言將任務的執行模式分成兩種:同步(Synchronous)和異步(Asynchronous)。

"同步模式"就是上一段的模式,后一個任務等待前一個任務結束,然后再執行,程序的執行順序與任務的排列順序是一致的、同步的;"異步模式"則完全不同,每一個任務有一個或多個回調函數(callback),前一個任務結束后,不是執行后一個任務,而是執行回調函數,后一個任務則是不等前一個任務結束就執行,所以程序的執行順序與任務的排列順序是不一致的、異步的。

"異步模式"非常重要。在瀏覽器端,耗時很長的操作都應該異步執行,避免瀏覽器失去響應,最好的例子就是Ajax操作。在服務器端,"異步模式"甚至是唯一的模式,因為執行環境是單線程的,如果允許同步執行所有http請求,服務器性能會急劇下降,很快就會失去響應。

同步

    console.log(1)
    function fn(){
        console.log(2)
    }
    fn()
    console.log(3)

上面代碼輸入1 2 3 ,因為js是單線程的,代碼由上而下依次執行

異步

js中

  • AJax請求
  • 定時器
  • 事件
  • 回調函數

上面這4中都是屬於異步的

    console.log(1)
    setTimeout(()=>{
        console.log(2)
    })
    console.log(3)

上面代碼執行會輸出,1 3 2 ,因為setTimeout是異步的,js會將setTimeout放到異步隊列,等待同步隊列全部執行完畢,在執行異步隊列

任務隊列

js中有兩類任務隊列:宏任務隊列和微任務隊列。宏任務隊列可以有多個,微任務隊列只有一個

  • 宏任務:script(全局任務),setTimeout,setInterval
  • 微任務:process.nextTick, Promise, Object.observer
setTimeout(_ => console.log(4))

new Promise(resolve => {
  resolve()
  console.log(1)
}).then(_ => {
  console.log(3)
})

console.log(2)

上面代碼中,setTimeout就是作為宏任務來存在的,而Promise.then則是具有代表性的微任務

所有會進入的異步都是指的事件回調中的那部分代碼

也就是說new Promise在實例化的過程中所執行的代碼都是同步進行的,而then中注冊的回調才是異步執行的。
在同步代碼執行完成后才回去檢查是否有異步任務完成,並執行對應的回調,而微任務又會在宏任務之前執行。所以就得到了上面的輸出1 2 3 4


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM