[Effective JavaScript 筆記]第7章:併發--個人總結

来源:http://www.cnblogs.com/wengxuesong/archive/2016/08/05/5742503.html
-Advertisement-
Play Games

前言 這一章的內容學到了事件隊列和非同步的API。js只是運行在其他應用程式的腳本語言。js即依賴於應用程式,也獨立與應用程式。可以使它可以在多平臺,多種環境上運行。ECMAScript標準中沒有關於併發的說明。這章討論的是一些常用的方法,使用事件和非同步API是js編程的基礎部分。非同步API,有set... ...


前言

這一章的內容學到了事件隊列和非同步的API。js只是運行在其他應用程式的腳本語言。js即依賴於應用程式,也獨立與應用程式。可以使它可以在多平臺,多種環境上運行。ECMAScript標準中沒有關於併發的說明。這章討論的是一些常用的方法,使用事件和非同步API是js編程的基礎部分。非同步API,有setTimeout,setInterval。

第61條:不要阻塞I/O事件隊列

個人總結

js是構建在事件之上的單線程語言。js處理交互都以事件的方法進行傳遞的,監聽事件的處理函數,都根據事件隊列的執行相應的監聽函數。

同步處理

同步處理,在一個I/O請求中,會等待輸入的內容。如果沒有輸入會一直等待下去,直到輸入有結果。這個時候,在多線程的語言里可以開另一個線程處理其他計算,但js是單線程的語言,只能一直等,也就是阻塞了,浪費了電腦資源。

非同步處理

在js中,可以為一個I/O操作提供一個回調函數,然後程式會繼續處理下麵的代碼。直到I/O有輸入時,回調函數才會執行相關操作。這是由事件隊列的特性來實現的,這樣就可以實現無阻塞的代碼。

提示

  • 非同步API使用回調函數來延緩處理代價高昂的操作以避免阻塞主應用程式

  • js併發地接收事件,但會使用一個事件隊列按序地處理事件處理程式

  • 在應用程式事件隊列中絕不要使用阻塞的I/O

第62條:在非同步序列中使用嵌套或命名的回調函數

個人總結

理解操作序列的最簡單的方式是非同步API的發起操作而不是執行操作。所以在發起操作後的代碼會先執行,而到後面的事件迴圈的輪次中,被註冊的事件處理程式才會執行。串聯已完成的非同步操作,可以使用嵌套的方式來進行。但層次過多會導致代碼很亂,很長。減少嵌套的方法:使用命名函數,使用bind方法來綁定。把這些方式結合在一起使用,可以更好解決問題。

提示

  • 使用嵌套或命名的回調函數按順序地執行多個非同步操作

  • 嘗試在過多的嵌套的回調函數和尷尬的命名的非嵌套回調函數之間取得平衡

  • 避免將可被並行執行的操作順序化

第63條:當心丟棄錯誤

個人總結

管理非同步編程,調試不太容易,錯誤發生的地方和錯誤捕獲的地方不好定位。這裡對非同步操作把錯誤的信息的以回調函數參數的形式向外層傳遞。在回調函數中對錯誤進行處理,可以使代碼可以正常運行。

提示

  • 通過編寫共用的錯誤處理函數來避免複製和粘貼錯誤處理代碼

  • 確保明確地處理所有的錯誤條件以避免丟棄錯誤

第64條:對非同步迴圈使用遞歸

個人總結

非同步迴圈,62條所說的一樣,這裡的迴圈只是同時發起了多個操作,但並不是執行操作。所以無法在執行操作中對迴圈進行中止。把迴圈的操作改寫成函數的遞歸,把非同步的發起和執行進行序列化。但又會有一個新的問題,js環境通常在記憶體中保存一塊固定的區域,稱為調用棧,用於記錄函數調用返回前下一步該做什麼。這是以棧的方式來存儲的“先進後出”。但如果這樣的調用次數過多,會導致棧空間被耗盡,最終會拋出異常,即棧溢出。

提示

  • 迴圈不能是非同步的

  • 使用遞歸函數在事件迴圈的單獨輪次中執行迭代

  • 在事件迴圈的單獨輪次中執行遞歸,並不會導致調用棧溢出

第65條:不要在計算時阻塞事件隊列

個人總結

第61條解釋了非同步API如何防止一段程式阻塞應用程式的事件隊列。如果是一段正常的執行代碼一直占用線程,事件隊列中的操作無法執行。這段時間里在瀏覽器環境中,無法響應
用戶操作。Web客戶端平臺的Worker API,可以處理純數據的計算,從而防止計算時對事件隊列的阻塞。

提示

  • 避免在主事件隊列中執行代價高昂的演算法

  • 在支持Worker API的平臺,該API可以用來在一個獨立的事件隊列中運行長計算程式

  • 在Worker API不可用或代價昂貴的環境中,考慮將計算程式分解到事件迴圈的多個輪次中

第66條:使用計數器來執行並行操作

個人總結

當處理多個併發時,無法保重回調函數中參數的順序。導致後期代碼無法正確運行,對於每次發起操作記一次數,返回時對對應的返回結果進行記錄。回調函數再對記錄的結果進行處理。可以保證程式按預定步驟進行運行。

提示

  • js應用程式中的事件發生是不確定的,即順序是不可預測的

  • 使用計數器避免並行操作中的數據競爭

第67條:絕不要同步地調用非同步的回調函數

個人總結

非同步的返回結果,可以保存在一個緩存中。在這種情況下,再進行多文件同步下載,可以使用緩存中的數據,所以回調函數可以同步地執行。但就像64條上的調用棧有可能會出現問題,會導致棧空間耗盡。回調函數也使用非同步調用,使用setTimeout來調用對應的回調函數。

提示

  • 即使可以立即得到數據,也絕不要同步地調用非同步回調函數

  • 同步地調用非同步的回調函數擾亂了預期的操作序列,並可能導致意想不到的交錯代碼

  • 同步地調用非同步的回調函數可能導致棧溢出或錯誤地處理異常

  • 使用非同步的API,比如setTimeout函數來調度非同步回調函數,使其運行於另一回合

第68條:使用promise模式清潔非同步邏輯

個人總結

使用promise模式,可以把多層嵌套函數,改寫成一種同步傳入回調函數的方式。這樣可以利用各種工具函數對其進行處理。如then,when,join,select等。

提示

  • promise代表最終值,即並行操作完成時最終產生的結果

  • 使用promise組合不同的並行操作

  • 使用promise模式的API避免數據競爭

  • 在要求有意的競爭條件時使用select(也被稱為choose)

總結

  • 非同步調用,利用事件隊列防止阻塞

  • 函數的多次遞歸調用,調用棧可能會耗盡

  • 純計算,使用web客戶端的Worker API

  • 使用計數器,可以保證非同步的結果順序

  • 使用處理非同步調用的工具框架

  • 可以防止數據競爭


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、引言 JavaScript的內容分為三個部分,這三個部分分別是ECMAScript、DOM、BOM三個部分組成。所謂ECMAScript就是JavaScript和核心基礎語法,DOM是文檔對象模型,最後剩下的BOM則是瀏覽器對象模型。這三個部分相輔相成組成了現在的JavaScript。 二、導入 ...
  • 在做WEB開發的時候我們經常會遇到分頁的處理,如果在PC上顯示網頁的話,使用傳統的分頁是可以接受的。那麼,當我們為手機或其他移動端設計界面的話,使用分頁未免有些笨拙和難以使用,這時候我們可以使用在單頁載入所有列表項。當屏幕滑動到最低端的時候,會出現“點擊載入更多”的按鈕,當我們點擊此按鈕的時候,會加 ...
  • 名字的聲明就是讓我的解釋器知道有這個名字 名字沒有任何數據與之對應 函數聲明包含兩部分 首先告訴解釋器函數的名字 告訴解釋器 這個名字對應的函數體是什麼 函數聲明與函數表達式有區別,函數聲明是單獨寫在一個結構中,不存在任何語句,邏輯判斷等結構中 ``` 函數聲明: function(){} func ...
  • 今天沒有說什麼內容,只是對HTML5的細節補充,如HTML結構的可以省略到最大的地步 沒有了基本的結構標簽了,瀏覽器會自動幫我們生成。 還有標簽的屬性的雙引號也可以省略; HTML5讓我體驗到它在最大化的簡化標簽,使代碼量最小化。 還有調試工具的使用,調試工具讓我們更快的更準確的查到各方面的信息, ...
  • <script> function lol(type) { if(typeof type == "undefined") { alert("undefined"); } else if(typeof type == "object") { if(new String(type) == "null") ...
  • 最近在這段時間瞭解了下redux,下麵簡單記錄下所得。 redux總結 首先,還是用幾句話簡單概括下redux吧,歡迎拍磚。 redux採用的函數式編程方式,基於單項數據流模式管理應用中的狀態。 一個複雜應用對應一個狀態樹,應用模塊之前共用的狀態都交由該狀態樹負責維護。 只能通過觸發action對象 ...
  • 本文記載boot 導航條組件使用方法 導航條組件 導航條是在您的應用或網站中作為導航頁頭的響應式基礎組件。它們在移動設備上可以摺疊(並且可開可關),且在視口(viewport)寬度增加時逐漸變為水平展開模式。 屏幕解析度變化時,頁面導航呈現不同效果,變小時會出現漢堡包按鈕,將頁面導航部分隱藏,以下拉 ...
  • × 目錄 [1]定義 [2]創建 [3]組成[4]引用 前面的話 javascript中的難點是函數、對象和繼承,前面已經介紹過函數系列。從本系列開始介紹對象部分,本文是該系列的第一篇——初識對象 對象定義 javascript的基本數據類型包括undefined、null、boolean、stri ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...