js 線程、宏觀任務、微觀任務、運行機制梳理

簡介

爲何要弄清楚線程和任務(宏、微)。咱們常常會被問到一個問題,就是當settimeout和http請求回調還有promise的執行順序。這裏就涉及到了這些知識點。以及爲何js過大影響dom渲染。html

本文適合有必定經驗的前端人員,對js運行機制有必定了解。前端

一、瀏覽器進程

首先咱們要知道瀏覽器在渲染一個頁面的過程種涉及到哪些工做原理。瀏覽器是多進程工做原理,什麼是進程請自行學習(進程是內存分配的最小單位),一個進程又能夠有多個線程(線程是執行的最小單位)。每打開一個tab標籤就是新啓一個進程(內存是獨立的)。node

二、瀏覽器內核

知道了瀏覽器進程,那麼說一下一個進程的渲染過程:web

  • GUI渲染線程(渲染Dom頁面的)
  • JS引擎線程(運行js的)
  • 事件觸發線程(js內的事件)
  • 定時觸發器線程
  • 異步http請求線程

注意:這些都是屬於瀏覽器的與js引擎單線程同樣是屬於瀏覽器的segmentfault

GUI渲染線程與JS引擎線程是互斥的。因此會JS若是執行時間過長就會阻塞頁面。promise

那麼咱們就能夠理解了,咱們常常遇到的問題,就是當js執行的時候遇到時間定時器、異步加載等,他們的輸出結果會在頁面全部js執行以後執行的問題了,就是當遇到到時間定時器、異步加載等瀏覽器的事件觸發線程就會觸發他會產生一個任務添加到js的任務對列內,同理異步http請求線程、事件觸發線程也是同樣的。瀏覽器

由進程產生的非js引擎的任務會分紅宏、微兩種任務對列。bash

三、宏、微兩種任務對列運行順序

宏任務包括有:setTimeOut、setInterval、setImmediate、I/O、用戶交互操做,UI渲染網絡

微任務包括有:Promise(重點)、process.nextTick(nodejs)、Object.observe(不推薦使用)多線程

運行順序是當js單線程執行完成以後就會去執行任務對列的內容。當有宏微都有的時候執行是,先執行宏觀任務對列內的第一個任務,在執行所有的微觀任務,在執行宏觀任務對列內的第一個任務,在去執行所有微觀任務。因此下面的代碼輸出結果是這個樣子的:

console.log(1)
      setTimeout(function() {
        //settimeout1
        console.log(2)
      }, 0);
      const intervalId = setInterval(function() {
        //setinterval1
        console.log(3)
      }, 0)
      setTimeout(function() {
        //settimeout2
        console.log(10)
        new Promise(function(resolve) {
          //promise1
          console.log(11)
          resolve()
        })
        .then(function() {
          console.log(12)
        })
        .then(function() {
          console.log(13)
          clearInterval(intervalId)
        })
      }, 0);
      
      //promise2
      Promise.resolve()
        .then(function() {
          console.log(7)
        })
        .then(function() {
          console.log(8)
        })
      console.log(9)
複製代碼

結果: 1,9,7,8,2,3,10,11,12,13

這裏注意: promise2執行,它的兩個then函數加入宏隊列

四、Web Worker解決JS若是執行時間過長就會阻塞頁面問題

Web Worker 的做用,就是爲 JavaScript 創造多線程環境,容許主線程建立 Worker 線程,將一些任務分配給後者運行。具體怎麼使用請自行學習。

Web Worker 有如下幾個使用注意點:

  • 同源限制:分配給 Worker 線程運行的腳本文件,必須與主線程的腳本文件同源。
  • DOM 限制:Worker 線程所在的全局對象,與主線程不同,沒法讀取主線程所在網頁的 DOM 對象,也沒法使用document、window、parent這些對象。可是,Worker 線程能夠navigator對象和lWorker 線程不能執行alert()方法和confirm()方法,但可使用 XMLHttpRequest 對象發出 AJAX 請求。ocation對象。
  • 通訊聯繫:Worker 線程和主線程不在同一個上下文環境,它們不能直接通訊,必須經過消息完成。使用worker.postMessage()通訊。
  • 腳本限制: Worker 線程不能執行alert()方法和confirm()方法,但可使用 XMLHttpRequest 對象發出 AJAX 請求。
  • 文件限制:Worker 線程沒法讀取本地文件,即不能打開本機的文件系統(file://),它所加載的腳本,必須來自網絡。

結尾

本文是是本身學習筆記,若有看不懂的可參考如下連接。

參考文章連接以下:

一、瀏覽器以及js運行原理:segmentfault.com/a/119000001…

二、宏觀任務和微觀任務原理:juejin.im/post/5da742…

三、Web Worker使用:www.ruanyifeng.com/blog/2018/0…

相關文章
相關標籤/搜索