JS—異步、回調、高階函數

併發與並行

  • 併發是指兩個或多個事件鏈隨時間發展交替執行,以致於從更高的層次來看,就像是同時運行(但在任意時刻只處理一個事件)
  • 併發的關鍵是你有處理多個任務的能力,不必定同時。
  • 並行的關鍵是你有同時處理多個任務的能力。
  • 併發和並行均可以是不少個線程,就看這些線程能不能同時被(多個)cpu執行,若是能夠就說明是並行,而併發是多個線程被(一個)cpu 輪流切換着執行。
  • 區別:是否【同時】

併發與並行

  • 單線程事件循環是併發的一種形式
  • 併發的實現方式:多進程,多線程,事件循環
  • 個人理解是:併發是多個邏輯流交替執行,看起來像是同時運行,其實任意時刻只能處理一個;而並行是真正的同時執行。

同步與異步

  • 同步和異步關注的是消息通訊機制 (synchronous communication/ asynchronous communication)
  • 同步,就是在發出一個調用時,在沒有獲得結果以前,該調用就不返回。可是一旦調用返回,就獲得返回值了。
  • 異步則是相反,調用在發出以後,這個調用就直接返回了,因此沒有返回結果。換句話說,當一個異步過程調用發出後,調用者不會馬上獲得結果。而是在調用發出後,被調用者經過狀態、通知來通知調用者,或經過回調函數處理這個調用。

阻塞與非阻塞

  • 阻塞和非阻塞關注的是程序在等待調用結果(消息,返回值)時的狀態
  • 阻塞調用是指調用結果返回以前,當前線程會被掛起。調用線程只有在獲得結果以後纔會返回。
  • 非阻塞調用指在不能馬上獲得結果以前,該調用不會阻塞當前線程。
  • 個人理解:異步阻塞是沒有必要的;ajax請求最好不要設置爲同步,chrome瀏覽器會警告

阻塞與非阻塞,同步與異步知乎連接
阻塞與非阻塞與是否同步異步無關javascript

事件循環

  • 機制:while(true)每輪循環取出事件隊列中的隊頭事件執行,事件隊列(先進先出)。
  • setTimeout()是設定一個定時器,當定時器到時後,環境會把回調函數放到事件循環中。若是此時事件隊列中有多個事件,那麼該回調就會等待,因此setTimeout定時器的精度可能不高,只能確保回調函數不會在指定的時間間隔以前運行。
  • AJAX請求:JS程序發出ajax請求,從服務器端獲取數據,並設置了回調函數。發出請求的時候,JS引擎會通知宿主環境,讓其完成了網絡請求,拿到數據後執行該回調函數。而後,瀏覽器會設置偵聽來自網絡的響應,拿到數據後,將該回調函數插入到事件循環。
  • 競態條件:函數執行順序的不肯定性(來自於插入事件隊列順序的不肯定性)
  • 競態條件可能會致使結果的不肯定性,因此須要經過協調交互順序來解決這種狀況。
  • 併發協做:JS中個人理解是:將大任務分解爲多個小任務,分別利用異步機制插入到事件隊列中,例如可利用setTimeout(f,0)將小任務插入到事件隊列中,若是事件隊列目前有待執行的事件就能夠先執行,以此來避免大任務阻塞事件隊列中其餘任務的執行。

JavaScript單線程與異步

  • why單線程:做爲瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操做DOM。這決定了它只能是單線程,不然會帶來很複雜的問題。
  • why異步:個人理解:瀏覽器應用決定了會有不少網絡請求,會有不少不可控的速度因素,瀏覽器是直接和用戶交互,用戶交互體驗很重要,因此不能阻塞,但同步非阻塞處理起來會很麻煩,由於同步須要編寫代碼去檢測任務是否執行成功。因此就用異步,異步是通訊機制決定了調用在發出以後就能夠直接返回。
  • 全部同步任務執行完畢,系統就會循環讀取事件隊列。
  • 阮一峯的連接:http://www.ruanyifeng.com/blo...
  • 深刻理解事件循環
  • 深刻事件循環

回調

  • 回調是JS中最基礎的異步模式
  • 回調地獄:1)難以編寫,大腦的思惟方式不適應面向回調的異步代碼。2)爲了處理可能出現的各類狀況,只能在回調的每一個步驟中硬編碼,形成代碼的複雜與重複,難以重用和維護。
  • 信任問題:控制反轉,即把本身程序的一部分執行控制交給了某個第三方。

高階函數

  • JS做爲一門完整的面向對象的編程語言,借鑑了函數式語言的特性,好比閉包、高階函數等。
  • 高階函數: 函數可做爲參數被傳遞,函數可做爲返回值輸出。
  • 函數做爲參數被傳遞:

1)回調函數,即將變化部分的代碼封裝爲函數,將函數做爲參數傳遞。原本能夠將變化的部分抽離出來,造成兩個函數,但實際上這兩個函數有依賴關係,因此只能參數調用,放到同一個函數中執行。
2)Array.prototype.sort 能夠傳入函數做爲排序規則。html

異步控制檯

  • JS調試最好使用斷點,由於console.log()是由宿主環境添加到JS中,控制檯I/O處理可能會有延時。

《你不知道的javascript中卷》第二部分異步和性能 1.1 異步控制檯部分: java

並無什麼規範或一組需求指定console.* 方法族如何工做——它們並非JavaScript 正式
的一部分,而是由宿主環境(請參考本書的「類型和語法」部分)添加到JavaScript 中的。所以,不一樣的瀏覽器和JavaScript 環境能夠按照本身的意願來實現,有時候這會引發混淆。 git

尤爲要提出的是,在某些條件下,某些瀏覽器的console.log(..) 並不會把傳入的內容當即輸出。出現這種狀況的主要緣由是,在許多程序(不僅是JavaScript)中,I/O 是很是低速的阻塞部分。因此,(從頁面/UI 的角度來講)瀏覽器在後臺異步處理控制檯I/O 可以提升性能,這時用戶甚至可能根本意識不到其發生。github

例如在mousemove監聽函數中console.log,是不會打印出內容的(mousemove觸發太頻繁,而console.log屬於I/O操做,瀏覽器爲了性能考慮,會將這種頻繁I/O放到後臺運行)。 ajax

解決方案: 若是斷點調試不方便的話,能夠將須要打印的內容,掛載到window對象,mousemove完成後再打印出來看。chrome

更多博客: https://github.com/Lmagic16/blog編程

相關文章
相關標籤/搜索