1. 程式人生 > >JS中的非同步

JS中的非同步

Hello,日常更新的我“浪”回來了!!!

JS中有三座高山:非同步和單執行緒、作用域和閉包、原型原型鏈

今天“浪”的主題是JS中的非同步和單執行緒的問題。

主要從這三個方面入手

一、什麼是非同步(與同步作比較)

二、前端使用非同步的場景

三、非同步和單執行緒

 

一:什麼是非同步 

說非同步之前我們先了解一下同步:同步可以簡單的來說就是順序執行

  console.log(100);

   alert(200)       //點選確定往下執行,如果不點選確定,就會阻塞不往下執行

   console.log(300)

  //列印100,彈出200(點選確定往下執行),列印300

 

接下來我們來說非同步(當執行非同步程式碼時,不會影響另一些程式碼執行)

  console.log(100);

   setTimeout(function() { //非同步執行,非阻塞並不妨礙後續程式碼執行
       console.log(300)

   }, 1000);

   console.log(200)

 

這段程式碼的執行結果為:

 

非同步和同步的區別就在於:

    同步:會阻塞後續程式碼的執行

    非同步:不會阻塞程式碼執行

 

二:前端使用非同步的場景

  1、定時任務:setTimeout  、 setInterval(程式碼同上)

  2、網路請求 :ajax請求、動態的建立<img>載入、

    console.log("start")
      $.get("./data.json",(data)=>{
          console.log(data)
      })
      console.log("end")

    //列印start,列印end 等待獲取回撥函式傳來的data資料渲染頁面
    //為啥ajax要用非同步呢?因為向伺服器請求資料,誰也不知道多長時間能返回資料(有可能幾秒,有可能拿不到資料)
     如果資料拿不到,頁面肯定還是要正常顯示的,所以必須是非同步

 

 

  

    console.log("start")
      var img = document.createElement("img");
      img.onload =function(){
          console.log("img is onload")
      }
      img.src='/aa.png'
      console.log("end")
    
    //列印start,列印end,載入圖片

 

 

  3、事件繫結

    console.log("start")
      document.getElementById("btn").addEventListener("click",()=>{ //ES6箭頭函式
          console.log("click is finshed")
      })
      console.log("end")

  //列印start,列印end,載入圖片

 

 

  

 三 、非同步和單執行緒

  下面程式碼和介紹非同步的程式碼區別是延時器沒有設定時間

   console.log(100);

   setTimeout(function() {
       console.log(300)
   });

   console.log(200)
  

 

 

   執行順序:

    先列印100,

    執行setTimeout,這個函式會被暫存起來,不會立即執行(因為單執行緒只能一個一個執行)

    列印300,

    等待所有的程式執行完後,瀏覽器會看有沒有暫存的,

    暫存裡面有setTimeout,setTimeout沒有設定時間,不用等待然後立刻執行

 

   那什麼叫單執行緒呢??

    簡單來說就是一次只能幹一件事,一個一個排隊,不能多個一起執行(因為不是多執行緒)

    標準定義:瀏覽器只分配給js一個主執行緒,用來執行任務(函式),但一次只能執行一個任務,這些任務形成一個任務佇列排隊等候執行,

    但前端的某些任務是非常耗時的,比如網路請求,定時器和事件監聽,如果讓他們和別的任務一樣,都老老實實的排隊等待執行的話,

    執行效率會非常的低,甚至導致頁面的假死。所以,瀏覽器為這些耗時任務開闢了另外的執行緒,主要包括http請求執行緒,瀏覽器定時觸發器,

    瀏覽器事件觸發執行緒,這些任務是非同步的。