js同步和異步


同步和異步

異步並不是同步,異步是單線程,異步指的是讓CPU暫時擱置當前請求的響應,處理下一個請求,當通過輪詢或其他方式得到回調通知后,開始運行。

並發是多線程,

 同步:一定要等任務執行完了,得到結果,才執行下一個任務。
 異步:不等任務執行完,直接執行下一個任務。

簡而言之,言而總之:同步就是我強依賴你(對方),我必須等到你的回復,才能做出下一步響應。即我的操作(行程)是順序執行的,中間少了哪一步都不可以,或者說中間哪一步出錯都不可以,類似於編程中程序被解釋器順序執行一樣;同時如果我沒有收到你的回復,我就一直處於等待、也就是阻塞的狀態。 異步則相反,我並不強依賴你,我對你響應的時間也不敏感,無論你返回還是不返回,我都能繼續運行;你響應並返回了,我就繼續做之前的事情,你沒有響應,我就做其他的事情。也就是說我不存在等待對方的概念,我就是非阻塞的。

我們先不深入異步概念,先從「表象」來看看怎么樣的代碼是異步代碼:

異步代碼的書寫順序與執行順序不同。

區別: 會不會阻塞當前程序運行

什么時候需要異步:

(1)需要等待的時候,等待過程不能卡在這吧

(2)等待過程不像alert一樣阻塞程序運行

(3)等待的情況都要異步

使用異步的場景:

(1)定時任務,setTimeout,setInterval

(2)網絡請求: ajax請求,動態<img>加載

(3)事件綁定,點擊等交互事件

 

 

 

幾個問題:

1. 同步和異步的區別是什么

   同步阻塞代碼運行,alert是同步,setTimeout是異步

2. 一個setTimeout的例子

JS引擎掃描一遍,將事件按順序加入任務隊列,然后執行,此時注意setTimeout中的函數是在定時完成后才會加入隊列

所以剛開始隊列中 有 console.log(1),setTimeout(fn1,0),console.log(3),setTimeout(fn2,1000),console.log(5)

輸出1,執行setTimeout后,再過0ms將fn1加入到任務隊列尾部,此時隊列中有console.log(3),setTimeout(fn2,1000),console.log(5),fn1

再輸出3,執行setTimeout,過了1000ms將fn2加到任務隊列尾部,輸出5,再執行fn1,fn2

事件執行過程中的事件循環,JS引擎有個運行棧,不斷從任務隊列里讀取任務運行,運行棧為空,便檢查任務隊列,一直加入,循環往復,直至任務隊列也為空

什么情況下需要用到異步?

現在有三個函數,taskA()、taskB() 和 taskC(),三個任務互不影響

taskA 和 taskC 執行得很快,但是 taskB 執行需要 10 秒鍾。

// 同步的寫法
function taskB(){
  var response = $.ajax({
    url:"/data.json",
    async: false // 注意這里 async 為 false,表示是同步
  })
  return response // 十秒鍾后,返回 response
}
 
taskA()
taskB()
taskC()

 

taskC 一定要等 taskB 執行完了才能執行,這就是同步。

執行順序為:

A -> B -> AJAX 請求 -> C ---------------------------

現在換成異步:

// 異步的寫法
function taskB(){
  var result = $.ajax({
    url:"/data.json",
    async: true // 異步
  })
  return result // 一定要注意,現在的 result 不是上面的 response
}
taskA()
taskB()
taskC()

 

這樣寫之后,執行順序就是

  1.  
    A -> B -> C ---------------------------------------
  2.  
    -> AJAX 請求 --------------------------------

就是說 AJAX 請求和任務C 同時執行。

但是請注意執行的主體。AJAX 請求是由瀏覽器的網絡請求模塊執行的,taskC 是由 JS 引擎執行的。

綜上,如果幾個任務互相獨立,其中一個執行時間較長,那么一般就用異步地方式做這件事。

所以像setTimeOut定時任務、ajax請求都是需要一定的時間的,所以一般都是用異步方式,不會阻塞后邊代碼的執行,而是設置了定時時間之后、或發送了請求之后,就移動到單線程的任務隊列的最尾端,等后邊執行完之后再執行定時代碼或者ajax請求的回調函數內代碼。

JS 引擎不能同時做兩件事

有些人說異步是同時做兩件事,但其實 JS 引擎不會這樣。

以 setTimeout 為例,setTimeout 里面的代碼一定會在當前環境中的任務執行完了「之后」才執行。

異步意味着不等待任務結束,並沒有強制要求兩個任務「同時」進行。

但是 AJAX 請求是可以與 JS 代碼同時進行的,因為這個請求不是由 JS 引擎負責,而是由瀏覽器網絡模塊負責。

以上,就是異步的簡介。


免責聲明!

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



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