[書籍精讀]《深入淺出Node.js》精讀筆記分享

来源:https://www.cnblogs.com/yzsunlei/archive/2020/05/21/12927454.html
-Advertisement-
Play Games

寫在前面 書籍介紹:本書由首章Node介紹為索引,涉及Node的各個方面,主要內容包含模塊機制的揭示、非同步I/O實現原理的展現、非同步編程的探討、記憶體控制的介紹、二進位數據Buffer的細節、Node中的網路編程基礎、Node中的Web開發、進程間的消息傳遞、Node測試以及通過Node構建產品需要的 ...


寫在前面

  • 書籍介紹:本書由首章Node介紹為索引,涉及Node的各個方面,主要內容包含模塊機制的揭示、非同步I/O實現原理的展現、非同步編程的探討、記憶體控制的介紹、二進位數據Buffer的細節、Node中的網路編程基礎、Node中的Web開發、進程間的消息傳遞、Node測試以及通過Node構建產品需要的註意事項。
  • 我的簡評:這是一本難得的好書,這本書理論和實踐結合的很好。如果你是一個純前端的開發者,這本書可以讀讀開拓些視野,如果你是一個全棧的開發者,這本書作為入門和深入後端也很不錯,推薦拜讀。
  • !!文末有pdf書籍、筆記思維導圖、隨書代碼打包下載地址,需要請自取!閱讀[書籍精讀系列]所有文章,請移步:推薦收藏-JavaScript書籍精讀筆記系列導航

第一章 Node簡介

1.1.Node的誕生歷程

  • 2009年3月, Ryan Dahl

1.2.Node的命名與起源

  • 別名 Nodejs、 NodeJS、 Node.js
  • 找到了設計高性能, Web伺服器的幾個要點: 事件驅動、非阻塞I/O
  • JavaScript 高性能、符合事件驅動、沒有歷史包袱
  • 構建網路應用的一個基礎框架

1.3.Node給JavaScript帶來的意義

  • 瀏覽器中除了V8作為JavaScript引擎外,還有一個WebKit佈局引擎
  • 瀏覽器通過事件驅動來服務界面上的交互, Node通過過事件驅動來服務I/O

1.4.Node的特點

  • 非同步I/O、事件與回調函數、單線程、跨平臺
  • 單線程:弱點1:無法利用多核CPU;弱點2:錯誤會引起整個應用退出,應用的健壯性值得考驗;弱點3:大量計算占用CPU導致無法繼續調用非同步I/O;Node採用與Web Workers相同的思路來解決單線程中大計算量的問題:child_process;
  • 跨平臺:在操作系統與Node上層模塊系統之間構建了一層平臺層架構,即libuv;Node的第三方C++模塊也可以藉助libuv實現跨平臺;

1.5.Node的應用場景

  • I/O密集型:面向網路且擅長並行I/O
  • 是否不擅長CPU密集型業務:採用使用多線程的方式進行計算;通過編寫C++擴展的方式更高效利用CPU;
  • 與遺留系統和平共處
  • 分散式應用:數據平臺、資料庫集群

1.6.Node的使用者

  • 前後端編程語言環境統一
  • Node帶來的高性能I/O用於實時應用
  • 並行I/O使得使用者可以更高效的利用分散式環境
  • 並行I/O,有效利用穩定介面提升Web渲染能力
  • 雲計算平臺提供Node支持
  • 游戲開發領域
  • 工具類應用

第二章 模塊機制

  • 大致經歷了工具類庫、組件庫、前端框架、前端應用的變遷

2.1.CommonJS規範

  • CommonJS的出發點:規範薄弱,以下缺陷(沒有模塊系統、標準庫較少、沒有標準介面、缺乏包管理系統)
  • CommonJS的模塊規範:主要分為模塊引用、模塊定義和模塊標識3個部分

2.2.Node的模塊實現

  • 優先從緩存載入:瀏覽器僅僅緩存文件,而Node緩存的是編譯和執行之後的對象
  • 路徑分析和文件定位:Node 會按.js、.json、.node的次序補足擴展名
  • 模塊編譯:每一個編譯成功的模塊都會將其文件路徑作為索引緩存在Module._cache對象上;在編譯的過程中,Node對獲取的JavaScript文件內容進行頭尾包裝;(function(exports, require, module, __filename, __dirname) {\n, 在尾部添加了\n});C/C++模塊,Node調用process.dlopen()方法進行載入和執行;

2.3.核心模塊

  • JavaScript核心模塊的編譯過程:C/C++文件放在Node項目的src目錄下,JavaScript文件存放在lib目錄下;編譯程式需要將所有的JavaScript模塊文件編譯為C/C++代碼;
  • C/C++核心模塊的編譯過程:Node在啟動時,會生成一個全局變數process,並提供Binding()方法來協助內建模塊

2.4.C/C++擴展模塊

  • 說明:JavaScript的一個典型弱點就是位運算;*nix下通過g++/gcc等編譯器編譯為動態鏈接共用對象文件.so,Windows下則需要通過VisualC++的編譯器編譯為動態鏈接庫文件.dll;
  • 前提條件:GYP項目生成工具、V8引擎C++庫、libuv庫、Node內部庫、等等
  • C/C++擴展模塊的編寫:普通的擴展模塊與內建模塊的區別在於無需將源代碼編譯進Node,而是通過dlopen()方法動態載入
  • C/C++擴展模塊的編譯:寫好.gyp項目文件是除編碼外的頭等大事;編譯過程會根據平臺不同,分別通過make或者vcbuild進行編譯;
  • C/C++擴展模塊的載入:require()方法通過解析標識符、路徑分析、文件定位,然後載入執行即可;載入.node文件實際上經歷了兩個步驟,第一個步驟是掉用uv_dlopen方法去打開動態鏈接庫,第二個步驟調用uv_dlsym()方法找到動態鏈接庫中通過NODE_MODULE巨集定義的方法地址;

2.5.模塊調用棧

  • JavaScript核心模塊主要扮演的職責有兩類:一類是作為C/C++內建模塊的封裝層和橋接層,供文件模塊調用;一類是純粹的功能模塊,不需要跟底層打交道

2.6.包和NPM

  • 包描述文件與NPM:包規範的定義可以幫助Node解決依賴包安裝的問題;NPM實際需要的欄位主要有name、version、description、keywords、repositories、author、bin、main、scripts、engines、dependencies、devDependencies;
  • NPM常用功能:NPM幫助完成了第三方模塊的發佈、安裝和依賴;查看幫助npm、分析包npm ls;
  • 局域NPM:能夠享受到NPM上眾多的包,同時對自己的包進行保密和限制
  • NPM潛在問題:開發人員水平不一,包質量也良莠不齊;NPM模塊首頁上的依賴榜可以說明模塊的質量和可靠性;GitHub上項目的觀察者數量和分支數量從側面反映模塊的可靠性和流行度;計劃引入CPAN社區中的Kwalitee風格來讓模塊進行自然排序;

2.7.前後端共用模塊

  • 模塊的側重點:前端通過網路載入代碼,瓶頸在於帶寬,後端從磁碟載入,瓶頸在於CPU和記憶體等資源
  • AMD規範:AMD模塊需要用define來明確定義一個模塊,而在Node實現中是隱式包裝的
  • CMD規範:CMD與AMD規範的主要區別在於定義模塊和依賴引入的部分
  • 相容多種模塊規範:包裝相容Node、AMD、CMD以及常見的瀏覽器環境中

第三章 非同步IO

  • 伴隨著非同步I/O的還有事件驅動和單線程

3.1.為什麼要非同步I/O

  • 用戶體驗:I/O是昂貴的,分散式I/O是更昂貴的
  • 資源分配:利用單線程,遠離多線程死鎖、狀態同步等問題;利用非同步I/O,讓單線程遠離阻塞,以更好的使用CPU

3.2.非同步I/O與實現現狀

  • 非同步I/O在Node中應用最為廣泛,但是它並非Node的原創
  • 非同步I/O與非阻塞I/O:操作系統內核對於I/O只有兩種方式:阻塞與非阻塞;現存的輪詢技術主要有:read,select,poll,epoll,kequeue(read:重覆調用來檢查I/O的狀態來完成完整數據的讀取;select:通過對文件描述符上的事件狀態來進行判斷;poll:採用鏈表的方式避免數組長度的限制,其次能避免不需要的檢查;epoll:Linux下效率最高的I/O事件通知機制;kqueue:與epoll類似,不過僅在FreeBSD系統下存在)
  • 理想的非阻塞非同步I/O
  • 現實的非同步I/O:在Node中,無論是*nix還是Windows平臺,內部完成I/O任務的另有線程池

3.3.Node的非同步I/O

  • 事件迴圈:Node自身的執行模型:事件迴圈
  • 觀察者:在Node中,事件主要來源於網路請求、文件I/O等;在Windows下,這個迴圈基於IOCP創建,而在*nix下則基於多線程創建;
  • 請求對象:從JavaScript發起調用到內核執行完I/O操作的過渡過程中存在的一種中間產物
  • 執行回調:事件迴圈、觀察者、請求對象、I/O線程池這四者共同構成Node非同步I/O模型的基本要素;完成非同步I/O的過程(Windows下通過IOCP向系統內核發送I/O調用和從內核獲取已完成的I/O操作,配以事件迴圈;Linux下通過epoll實現;FreeBSD下通過kqueue實現;Solaris下通過Event ports實現)

3.4.非I/O的非同步API

  • 與I/O無關的非同步API:setTimeout()、setInterval()、setImmedate()、process.nextTick()
  • 定時器:實現原理與非同步I/O比較類似,只是不需要I/O線程池的參與;問題在於並非精確的;
  • process.nextTick():採用定時器需要動用紅黑樹,創建定時器對象和迭代等操作;定時器中採用紅黑樹的操作時間複雜度為O(lg(n)),nextTick()的時間複雜度為O(1);
  • setImmediate():process.nextTick()中的回調函數執行的優先順序要高於setImmediate();process.nextTick()屬於idle觀察者,setImmediate()屬於check觀察者;

3.5.事件驅動與高性能伺服器

  • Node無需為每一個請求創建額外的對應線程
  • 不受線程上下文切換開銷的影響
  • 一些知名的基於事件驅動的實現:Ruby的Event Machine;Perl的AnyEvent;Python的Twisted;

第四章 非同步編程

  • Node是首個將非同步大規模帶到應用層面的平臺

4.1.函數式編程

  • 高階函數:高階函數是可以把函數作為參數,或是將函數作為返回值的函數
  • 偏函數用法:偏函數用法是指創建一個調用另外一個部分參數或變數已經預置的函數的函數的用法;通過指定部分參數來產生一個新的定製函數的形式就是偏函數;

4.2.非同步編程的優勢與難點

  • 優勢:Node的非同步模型和V8的高性能
  • 難點:異常處理、函數嵌套、阻塞代碼、多線程編程、非同步轉同步

4.3.非同步編程解決方案

  • 事件發佈/訂閱模式:如果一個事件添加了超過10個偵聽器將會得到一條警告,使用emitter.setMaxListeners(0)去掉限制
  • Promise/Deferred模式:Deferred主要是用於內部,用於維護非同步模型的狀態;Promise則作用與外部,通過then()方法暴露給外部以添加自定義邏輯;Promise/Deferred模式將業務中不可變的部分封裝在了Deferred,將可變的部分交給Promise;
  • 流程式控制制庫:尾觸發與Next,目前應用最多的地方是Connect的中間件;async,長期占據NPM依賴榜的前三名,series實現非同步的串列執行,parallel實現非同步的並行執行,waterfall實現非同步調用的依賴處理;step,更輕量;wind,思路完全不同的非同步編程方案;

4.4.非同步併發控制

  • 同步I/O,每個I/O都是彼此阻塞的,不會出現耗用文件描述符太多的情況
  • bagpip的解決方案:bagpipe模塊的解決思路(通過一個隊列來控制併發量;調用發起但未執行的非同步調用量小於限定值,從隊列中取出執行;如果活躍調用達到限定值,調用暫時存放在隊列中;每一個非同步調用結束時,從隊列中取出新的非同步調用執行;);拒絕訪問;超時控制;
  • async的解決方案:async中parallelLimit()用於處理非同步調用的限制

第五章 記憶體控制

  • 基於無阻塞、事件驅動建立的Node服務,具有記憶體消耗低的優點,非常適合處理海量的網路請求

5.1.V8的垃圾回收機制與記憶體限制

  • Node與V8
  • V8的記憶體限制:只能使用部分記憶體(64位系統下約為1.4G,32位系統下約為0.7G)
  • V8的對象分配:V8依然提供選項讓我們使用更多的記憶體;--max-old-space-size設置老生代記憶體空間的最大值;--max-new-space-size設置新生代記憶體空間大小;
  • V8的垃圾回收機制:垃圾回收策略主要基於分代式垃圾回收機制;在分代的基礎上,新生代的對象主要通過Scavenge演算法進行垃圾回收;V8在老生代中主要採用Mark-Sweep和Mark-Compact相結合的方式進行垃圾回收;
  • 查看垃圾回收日誌:在啟動時添加--trace-gc參數;node啟動時使用--prof參數,可以得到V8執行時的性能分析數據;提供linux-tick-processor工具用於統計日誌信息;

5.2.高效使用記憶體

  • 作用域:能形成作用域的有函數調用、with以及全局作用域
  • 閉包:實現外部作用域訪問內部作用域中變數的方法
  • 無法立即回收的記憶體有閉包和全局變數引用這兩種情況

5.3.記憶體指標

  • 查看記憶體使用情況:process.memoryUsage()可以看到Node進程的記憶體占用情況;os模塊的totalmem()和freemem()查看系統的總記憶體和閑置記憶體;
  • 堆外記憶體:不通過V8分配的記憶體稱為堆外記憶體;利用堆外記憶體可以突破記憶體限制的問題;

5.4.記憶體泄露

  • 造成記憶體泄露的原因幾個:緩存、隊列消費不及時、作用域未釋放
  • 慎將記憶體當作緩存:在Node中任何試圖拿記憶體當緩存的行為都應當被限制
  • 關註隊列狀態:使任何非同步調用的回調都具備可控的響應時間

5.5.記憶體泄露排查

  • 常見的用於定位Node應用記憶體泄露的工具:v8-profiler、node-headpdump、node-mtrace、dtrace、node-memwatch
  • node-headdump
  • node-memwatch

5.6.大記憶體應用

  • Node提供了stream模塊用於處理大文件
  • 要小心,即使V8不限制堆記憶體的大小,物理記憶體依然有限制

第六章 理解Buffer

6.1.Buffer結構

  • 模塊結構:Buffer是一個像Array的對象,但它主要用於操作對象
  • Buffer對象:buf[10]的元素值是一個0到255的隨機值
  • Buffer記憶體分配:Buffer對象的記憶體分配不是在V8的堆記憶體中,而是在Node的C++層面實現記憶體的申請的;Node以8KB為界限來區分Buffer是大對象還是小對象;真正的記憶體是在Node的C++層面提供的,JavaScript層面只是使用它;

6.2.Buffer的轉換

  • 目前支持的字元串編碼類型:ASCII、UTF-8、UTF-16LE/UCS-2、Base64、Binary、Hex
  • 字元串轉Buffer
  • Buffer轉字元串
  • Buffer不支持的編程類型:Buffer提供一個isEncoding()函數來判斷編碼是否支持轉換;iconv和iconv-lite兩個模塊可以支持更多的編碼類型轉換;

6.3.Buffer的拼接

  • 亂碼是如何產生的
  • setEncode()與string_decoder()
  • 正確拼接Buffer:調用Buffer.concat()方法生成一個合併的Buffer對象

6.4.Buffer與性能

  • Buffer在文件I/O和網路I/O中運用廣泛
  • Buffer是二進位數據,字元串與Buffer之間存在編碼關係

第七章 網路編程

  • Node提供了net、dgram、http、https這4個模塊,分別用於處理TCP、UDP、HTTP、HTTPS

7.1.構建TCP服務

  • TCP
  • 創建TCP伺服器端
  • TCP服務的事件:TCP套接字是可寫可讀的Stream對象,可以利用pipe()方法巧妙的實現管道操作

7.2.構建UDP服務

  • 創建UDP套接字
  • 創建UDP伺服器端
  • 創建UDP客戶端
  • UDP套接字事件:UDP套接字只是一個EventEmitter的實例,而非Stream的實例

7.3.構建HTTP服務

  • HTTP
  • http模塊:TCP服務以connection為單位進行服務,HTTP服務以request為單位進行服務
  • HTTP客戶端

7.4.構建WebSocket服務

  • WebSocket握手
  • WebSocket的數據傳輸

7.5.網路服務與安全

  • Node在網路安全上提供了3個模塊,分別為crypto、tls、https
  • TLS/SSL
  • TLS服務
  • HTTPS服務

第八章 構建Web應用

8.1.基礎功能

  • 請求方法
  • 路徑解析
  • 查詢字元串
  • Cookie:Cookie處理的幾步(伺服器向客戶端發送cookie;瀏覽器將Cookie保存;之後每次瀏覽器都會將Cookie發向伺服器端)
  • Session:常見的兩種實現方式(基於Cookie來實現用戶和數據的映射;通過查詢字元串來實現瀏覽器端和伺服器端數據的對應);Connect預設採用connect_uid,Tomcat會採用jsessionid等;
  • 緩存:提高性能,YSlow中提到的幾條關於緩存的規則(添加Expires或Cache-Control到報文中;配置ETags;讓Ajax可緩存)
  • Basic認證:通過Base64加密後在網路中傳送,有太多的缺點

8.2.數據上傳

  • 表單數據:通過報頭的Transfer-Encoding或Content-Length即可判斷請求中是否帶有內容
  • 附件上傳:瀏覽器在遇到multipart/form-data表單提交時,構造的請求報文與普通表單完全不同;formidable,基於流式處理解析報文,將接收到的文件寫入到系統的臨時文件夾中,並返回對應的路徑;
  • 數據上傳與安全

8.3.路由解析

  • 文件路徑型
  • MVC
  • RESTful

8.4.中間件

  • 異常處理
  • 中間件與性能
  • 從凌亂的發散狀態收斂成很規整的組織方式

8.5.頁面渲染

  • 內容響應:不同的文件類型具有不同的Mime值;Content-Disposition欄位影響的行為是客戶端會根據它的值判斷是應該將報文數據當作即時瀏覽的內容,還是可下載的附件;
  • 視圖渲染
  • 模板:實質就是將模板文件和數據通過模板引擎生成最終的HTML代碼;形成模板技術4個要素(模板語言;包含模板語言的模板文件;擁有動態數據的數據對象;模板引擎);mustache,弱邏輯的模板;最知名的有EJS、Jade等;
  • Bigpipe:用於調用限流,解決重數據頁面的載入速度問題;解決思路是將頁面分割成多個部分,先向用戶輸出沒有數據的佈局,將每個部分逐步輸出到前端,再最渲染填充框架,完成整個網頁的渲染;

第九章 玩轉進程

9.1.服務模型的變遷

  • 石器時代:同步 - 只在一些無併發要求的應用中存在
  • 青銅時代:複製進程 - 要複製較多的數據,啟動是較為緩慢的
  • 白銀時代:多進程 - 時間將會被耗用在上下文切換中
  • 黃金時代:事件驅動 - 記憶體耗用的問題著名的C10k問題;單線程避免了不必要的記憶體開銷和上下文切換開銷;

9.2.多進程架構

  • child_process.fork()複製的都是一個獨立的進程,獨立而全新的V8實例
  • 啟動多個進程只是為了充分將CPU資源利用起來,而不是為瞭解決併發問題
  • 創建子進程
  • 進程間通信:JavaScript主線程與UI渲染共用同一個線程;實現進程間通信的技術有很多,如命名管道、匿名管道、socket、信號量、共用記憶體、消息隊列、Domain Socket等;操作系統的文件描述符是有限的;
  • 句柄傳遞:句柄是一種可以用來標識資源的引用,它的內部包含了指向對象的文件描述符;文件描述符實際上是一個整數值;Node進程之間只有消息傳遞,不會真正的傳遞對象;

9.3.集群穩定之路

  • 進程事件
  • 自動重啟:創建新工作進程在前,退出異常進程在後
  • 負載均衡:輪叫調度的工作方式是由主進程接受連接,將其依次分發給工作進程
  • 狀態共用:解決數據共用最簡單、直接的方式就是通過第三方進行數據存儲;主動通知;

9.4.Cluster模塊

  • Cluster工作原理:事實上是child_process和net模塊的組合應用
  • Cluster事件

第十章 測試

10.1.單元測試

  • 編寫可測試代碼的幾個原則:單一職責、介面抽象、層次分離;
  • 單元測試主要包含斷言、測試框架、測試用例、測試覆蓋率、mock、持續繼承等,由於Node的特殊性,還會加入非同步代碼測試和私有方法的測試;
  • JavaScript的斷言規範最早來自於CommonJS的單元測試規範;
  • 單元測試風格主要有TDD(測試驅動開發)和BDD(行為驅動開發)兩種;
  • BDD對測試用例的組織主要採用describe和it進行組織;
  • TDD對測試用例的組織主要採用suite和test完成;
  • 單元測試覆蓋率方便我們定位沒有測試到的代碼行;
  • 私有方法的測試(Java一類的語言,私有方法訪問可以通過反射的方式實現;巧妙利用閉包的訣竅,在eval()執行時,實現對模塊內部局部變數的訪問,從而可以將局部變數導出給測試用例調用執行;)

10.2.性能測試

  • 單元測試主要用於檢測代碼的行為是否符合預期,性能測試的範疇比較廣泛,包括負載測試、壓力測試和基準測試
  • 基準測試
  • 壓力測試:最常用的工具是ab、siege、http_load等
  • 基準測試驅動開發
  • 測試數據與業務數據的轉換

第十一章 產品化

11.1.項目工程化

  • 目錄結構
  • 構建工具:在Web應用中通常會在Makefile文件中編寫一些構建任務來幫助提升效率;合併編譯、應用打包、運行測試、清理目錄、掃描代碼等;
  • 編碼規範:一種是文檔式的約定,一種是代碼提交時的強制檢查
  • 代碼審查

11.2.部署流程

  • 部署環境
  • 部署操作

11.3.性能

  • 幾個拆分原則:做專一的事;讓擅長的工具做擅長的事情;將模型簡化;將風險分離;
  • 動靜分離
  • 啟動緩存
  • 多進程架構
  • 讀寫分離:進行資料庫的讀寫分離,將資料庫進行主從設計

11.4.日誌

  • 訪問日誌
  • 異常日誌:log與info方法都將信息輸出給標準輸出process.stdout,warn與error方法則將信息輸出到標準錯誤process.stderr;console對象上有個Console屬性,它是console對象的構造函數;回調函數中產生的異常,交給全局的uncaughtException事件去捕獲;
  • 日誌與資料庫
  • 分割日誌

11.5.監控報警

  • 監控:一種是業務邏輯型的監控,一種是硬體型的監控;主要指標:日誌監控、響應時間、進程監控、磁碟監控、記憶體監控、CPU占用監控、CPU load監控、I/O負載、網路監控、應用狀態監控、DNS監控;
  • 報警的實現
  • 監控系統的穩定性

11.6.穩定性

  • 典型的水平擴展方式就是多進程、多機器、多機房

寫在後面


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

-Advertisement-
Play Games
更多相關文章
  • 前言: 本文詳細介紹了 HBase DependentColumnFilter 過濾器 Java&Shell API 的使用,並貼出了相關示例代碼以供參考。DependentColumnFilter 也稱參考列過濾器,是一種允許用戶指定一個參考列或引用列來過濾其他列的過濾器,過濾的原則是基於參考列的 ...
  • 前言: 本文詳細介紹了 HBase ValueFilter 過濾器 Java&Shell API 的使用,並貼出了相關示例代碼以供參考。ValueFilter 基於列值進行過濾,在工作中涉及到需要通過HBase 列值進行數據過濾時可以考慮使用它。比較器細節及原理請參照之前的更文: "HBase Fi ...
  • A.前言:為瞭解決安卓端向伺服器上傳照片的問題 1.獲得相冊許可權,選取照片,取到照片的url 2.使用okhttp訪問伺服器並向伺服器傳照片 3.配置springmvc文件解析器 4.搭建伺服器,獲取數據保存照片 B.Android添加一個按鈕和一個ImageView,設置它的點擊事件,打開相冊選擇 ...
  • 1.這裡編寫一個類用於開啟活動,首先在onCreateView()方法中載入了我們剛剛創建的news_content_frag佈局,這個沒什麼好解釋的,接下來又提供了一個refresh()方法,這個方法就是用於將新聞的標題和內容顯示在界面上的。可以看到,這裡通過findViewById()方法分別獲 ...
  • 插件 1. "get" Navigate between screens, display snackbars, dialogs and bottomSheets, from anywhere in your code without context with Get. 1. "FlutterVis ...
  • 淺析Block閉包 簡單來說,block就是將函數及其上下文封裝起來的對象,從功能上可以把它看作是C++中的匿名函數,也可稱之為塊。 Block類型寫法: 返回值+(^塊名)+(參數)= ^(參數){ 內容 } 如下所示: Block結構 Block存儲區域 Block本質上也是OC對象,所以每個B ...
  • 再探NSString NSString應該是oc開發中最常用的一個數據類型了,這次對該類型再進行一次全方位的探索與總結。 NSString本質上屬於OC類對象,繼承於NSObject,遵守NSCopying, NSMutableCopying, NSSecureCoding協議。 NSMutable ...
  • OC屬性與實例變數 無論是java還是c++這些面向對象的語言都會有屬性這一概念,通常而言,對於java屬性和實例變數沒有什麼區別,java官方定義的屬性如下: 屬性是指get或者set方法名 去掉get或者set後,把剩餘的部分首字母改為小寫後,即為這個類的 屬性 其實objective C與之類 ...
一周排行
    -Advertisement-
    Play Games
  • C#TMS系統代碼-基礎頁面BaseCity學習 本人純新手,剛進公司跟領導報道,我說我是java全棧,他問我會不會C#,我說大學學過,他說這個TMS系統就給你來管了。外包已經把代碼給我了,這幾天先把增刪改查的代碼背一下,說不定後面就要趕鴨子上架了 Service頁面 //using => impo ...
  • 委托與事件 委托 委托的定義 委托是C#中的一種類型,用於存儲對方法的引用。它允許將方法作為參數傳遞給其他方法,實現回調、事件處理和動態調用等功能。通俗來講,就是委托包含方法的記憶體地址,方法匹配與委托相同的簽名,因此通過使用正確的參數類型來調用方法。 委托的特性 引用方法:委托允許存儲對方法的引用, ...
  • 前言 這幾天閑來沒事看看ABP vNext的文檔和源碼,關於關於依賴註入(屬性註入)這塊兒產生了興趣。 我們都知道。Volo.ABP 依賴註入容器使用了第三方組件Autofac實現的。有三種註入方式,構造函數註入和方法註入和屬性註入。 ABP的屬性註入原則參考如下: 這時候我就開始疑惑了,因為我知道 ...
  • C#TMS系統代碼-業務頁面ShippingNotice學習 學一個業務頁面,ok,領導開完會就被裁掉了,很突然啊,他收拾東西的時候我還以為他要旅游提前請假了,還在尋思為什麼回家連自己買的幾箱飲料都要叫跑腿帶走,怕被偷嗎?還好我在他開會之前拿了兩瓶芬達 感覺感覺前面的BaseCity差不太多,這邊的 ...
  • 概述:在C#中,通過`Expression`類、`AndAlso`和`OrElse`方法可組合兩個`Expression<Func<T, bool>>`,實現多條件動態查詢。通過創建表達式樹,可輕鬆構建複雜的查詢條件。 在C#中,可以使用AndAlso和OrElse方法組合兩個Expression< ...
  • 閑來無聊在我的Biwen.QuickApi中實現一下極簡的事件匯流排,其實代碼還是蠻簡單的,對於初學者可能有些幫助 就貼出來,有什麼不足的地方也歡迎板磚交流~ 首先定義一個事件約定的空介面 public interface IEvent{} 然後定義事件訂閱者介面 public interface I ...
  • 1. 案例 成某三甲醫預約系統, 該項目在2024年初進行上線測試,在正常運行了兩天後,業務系統報錯:The connection pool has been exhausted, either raise MaxPoolSize (currently 800) or Timeout (curren ...
  • 背景 我們有些工具在 Web 版中已經有了很好的實踐,而在 WPF 中重新開發也是一種費時費力的操作,那麼直接集成則是最省事省力的方法了。 思路解釋 為什麼要使用 WPF?莫問為什麼,老 C# 開發的堅持,另外因為 Windows 上已經裝了 Webview2/edge 整體打包比 electron ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...