日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

js执行机制

發布時間:2024/4/17 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 js执行机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在寫js代碼的時候我們往往都希望js代碼的執行順序是按照自己所想那樣執行,但結果總事與愿違。所以今天就想花時間搞懂js的事件執行機制到底是什么樣的。

EventLoop事件循環機制

js中事件分為宏任務和微任務兩類,任務又分為同步任務和異步任務。他們之間的執行順序將依次進行說明

js中事件的同步異步的執行順序

js中事件分為兩類

  • 同步事件
  • 異步事件
  • js執行順序:先執行同步再執行異步
  • js在執行時如果遇到同步任務就直接放入主線程執行
  • 如果遇到異步任務就將其放入event table 中并注冊函數
  • 當異步事件完成后會將他的放入Event Queue中等待執行(這里特別說明宏任務和微任務各自有一個Event Queue)
  • 那么等到什么時候才能執行呢?就是等到主線程的任務執行完畢為空的時候。那我們怎么知道什么時候主線程為空呢?js引擎存在monitoring process進程,會持續不斷的檢查主線程執行棧是否為空,一旦為空,就會去Event Queue那里檢查是否有等待被調用的函數。 用流程圖來概括上述步驟:

    • 代碼示例
    let data = []; $.ajax({url:www.javascript.com,data:data,success:() => {console.log('發送成功!');} }) console.log('代碼執行結束'); 復制代碼
  • 從上往下,先遇到$.ajax異步請求,所以ajax進入event table中注冊回調函數success
  • 然后執行同步任務console.log("代碼執行結束")
  • ajax請求完成,回調函數success進入Event Queue
  • 主線程任務執行完畢,從Event Queue中讀取回調函數success并執行
  • js中事件的宏任務與微任務的執行順序

    js中任務分為兩類

    • 宏任務:包括整體代碼script,setTimeout,setInterval
    • 微任務:Promise.then(非new Promise),process.nextTick(node中)
    • js執行順序:先執行宏任務再執行微任務
  • js執行事件時先執行線程或Event Queue的宏任務
  • 當前事件的宏任務執行完畢查看此線程或Event Queue是否有微任務,有的話執行微任務,沒有的話執行新的宏任務
  • 用流程圖表示上述流程:

    • 代碼示例
    setTimeout(function() {console.log('setTimeout'); },1000)new Promise(function(resolve) {console.log('promise'); }).then(function() {console.log('then'); })console.log('console'); 復制代碼
  • 首先遇到了setTimeout函數,他是異步任務,所以將它放入event table中注冊回調函數,又因為setTimeout是宏任務,所以1秒后將setTimeout放入宏任務的Event Queue中等待執行。
  • 遇到同步代碼new promise放入主線程直接開始執行
  • 執行new promise的console.log('promise')然后看到.then是微任務因此將其放入微任務的Event Queue中
  • 接下來執行同步代碼console.log('console')
  • 主線程的宏任務,已經執行完畢,接下來要執行微任務,因此會執行Event Queue中的Promise.then,到此,第一輪事件循環執行完畢
  • 第二輪事件循環開始,先執行宏任務,即setTimeout的回調函數,然后查找是否有微任務,沒有,時間循環結束
  • 現在看一個比較復雜的例子

    console.log('1'); setTimeout(function() {console.log('2');process.nextTick(function() {console.log('3');})new Promise(function(resolve) {console.log('4');resolve();}).then(function() {console.log('5')}) }) 輸出: 1 2 4 3 5 復制代碼
  • 同步代碼console.log('1')直接放入主線程執行
  • setTimeout異步代碼放到event table中注冊回調函數,setTimeout事件完成將其回調函數放入宏任務的Event Queue中等待執行
  • 然后主線程為空,先在宏任務的Event Queue中讀取回調函數運行,直接執行console.log('2');
  • 然后遇到process.nextTick放入微任務的Event Queue中
  • 遇到new Promise執行console.log('4')然后將.then放入微任務的Event Queue中
  • 宏任務執行完畢,查看微任務的Event Queue中是否有等待執行的微任務
  • 執行process.nextTick的console.log('3')
  • 執行.then的console.log('5')
  • js中的同步和異步

    大家都知道js是是一門單線程語言,所以他的語句肯定是一句一句執行的。但是js中又存在同步操作和異步操作,那么就會有疑問,js是如何通過單線程的方式來實現異步操作的呢?

    什么是同步操作

    當函數執行的時候,按照函數內部的順序依次執行,比如:如果此調用的函數是很耗時的,但它依然會等待調用函數的返回值,直到拿到預期的結果(即拿到了預期的返回值或者看到了預期的效果)為止才會執行后面的操作,那么這個函數就是同步的。

    //在函數返回時,獲得了預期值,即2的平方根 Math.sqrt(2); //在函數返回時,獲得了預期的效果,即在控制臺上打印了'hello' console.log('hello');復制代碼

    什么是異步操作

    如果函數是異步的,發出調用之后,馬上返回,但是不會馬上返回預期結果。調用者不必主動等待,當被調用者得到結果之后會通過回調函數主動通知調用者。

    //讀取文件 fs.readFile('hello.txt', 'utf8', function(err, data) {console.log(data); }); //網絡請求 var xhr = new XMLHttpRequest(); xhr.onreadystatechange = xxx; // 添加回調函數 xhr.open('GET', url); xhr.send(); // 發起函數 復制代碼

    上述示例中讀取文件函數 readFile和網絡請求的發起函數 send都將執行耗時操作,雖然函數會立即返回,但是不能立刻獲取預期的結果,因為耗時操作交給其他線程執行,暫時獲取不到預期結果(后面介紹)。而在JavaScript中通過回調函數 function(err, data) { console.log(data); }和 onreadystatechange ,在耗時操作執行完成后把相應的結果信息傳遞給回調函數,通知執行JavaScript代碼的線程執行回調。

    瀏覽器

    前面說到js是一門單線程語言,他是怎么實現異步操作的呢。JS的運行通常是在瀏覽器中進行的,具體由JS引擎去解析和運行。下面我們來具體了解一下瀏覽器。 瀏覽器的內核是多線程的。 一個瀏覽器通常由以下幾個常駐的線程:

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

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

    JS引擎可以說是JS虛擬機,負責JS代碼的解析和執行。之所以說JavaScript是單線程,就是因為瀏覽器在運行時只開啟了一個JS引擎線程來解析和執行JS。那為什么只有一個引擎呢?如果同時有兩個線程去操作DOM,瀏覽器是不是又要不知所措了。 所以,雖然JavaScript是單線程的,可是瀏覽器內部不是單線程的。一些I/O操作、定時器的計時和事件監聽(click, keydown...)等都是由瀏覽器提供的其他線程來完成的。也就是之前說的Event Queue。

    參考文章

    JavaScript異步機制詳解
    這一次,徹底弄懂 JavaScript 執行機制
    簡單總結下JS中EventLoop事件循環機制

    總結

    以上是生活随笔為你收集整理的js执行机制的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。