<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [NodeJS] NodeJS運(yùn)行原理簡(jiǎn)記

      NodeJS的基本組成

      NodeJS是JavaScript運(yùn)行時(shí),主要由V8引擎和libuv組成,其中V8使用 javascript 和 c++ 編寫,而libuv是純 c++ 編寫的,二者都是開源的。

      image-20240707155536398

      V8引擎用于將 javascript 代碼轉(zhuǎn)換為計(jì)算機(jī)可以執(zhí)行的機(jī)器碼;

      而libuv則負(fù)責(zé)完成異步IO、與操作系統(tǒng)交互(文件系統(tǒng)和網(wǎng)絡(luò)模塊)、事件循環(huán)、線程池等等。

      Node還有其它模塊:

      • http-parser:用于解析http;
      • c-ares:用于處理DNS請(qǐng)求;
      • OpenSSL:用于加密和安全編程;
      • zlib:與壓縮有關(guān)。

      總而言之,NodeJS相當(dāng)于Javascript和操作系統(tǒng)之間的一個(gè)抽象層,為開發(fā)人員提供了API,使得開發(fā)人員可以編寫純JavaScript代碼來操控操作系統(tǒng)。

      NodeJS的特點(diǎn)

      • 單線程,基于事件驅(qū)動(dòng)的非阻塞IO模型,使得NodeJS非常輕量級(jí)和高效;
      • 適用于需要快速且可擴(kuò)展的數(shù)據(jù)密集型Web應(yīng)用程序,例如:
        • 帶有數(shù)據(jù)庫的API(最好是像MongoDB這樣的NoSQL數(shù)據(jù)庫);
        • 數(shù)據(jù)流式傳輸
        • 實(shí)時(shí)聊天應(yīng)用
        • 服務(wù)端Web應(yīng)用(例如使用Pug這種模板引擎的模式)
      • 不適用于CPU密集型的服務(wù)端處理任務(wù),例如圖像處理、視頻轉(zhuǎn)換、文件壓縮等等。

      NodeJS程序的工作流程

      NodeJS工作在單線程中,在開發(fā)后端服務(wù)的時(shí)候,應(yīng)該時(shí)刻注意不要阻塞這個(gè)線程。

      在啟動(dòng)NodeJS進(jìn)程之后,主線程的工作流程如下:

      1. 初始化程序 initialize program
      2. 執(zhí)行頂層代碼 execute top-level code
      3. 獲取依賴模塊 require modules
      4. 注冊(cè)回調(diào)事件 register event callbacks
      5. 啟動(dòng)事件循環(huán) start event loop

      事件循環(huán)是整個(gè)Node應(yīng)用的核心,只能應(yīng)付簡(jiǎn)單的任務(wù),開銷較大的任務(wù)不能在事件循環(huán)中執(zhí)行,否則會(huì)阻塞主線程(對(duì)于后端服務(wù)來說是致命的)。

      開銷較大的任務(wù)實(shí)際上會(huì)被卸載到libuv提供的線程池中執(zhí)行,線程池默認(rèn)的數(shù)量是4,可以配置,至多128個(gè)。(配置項(xiàng)是process.env.UV_THREADPOLL_SIZE

      如何卸載任務(wù)和卸載哪些任務(wù)到線程池是由Node處理的,與開發(fā)人員無關(guān)。會(huì)被卸載到線程池執(zhí)行的任務(wù)是計(jì)算開銷比較大的,比如:

      1. 文件系統(tǒng)API
      2. 與密碼學(xué)相關(guān)的API
      3. 與壓縮有關(guān)的操作
      4. DNS查詢

      事件循環(huán)

      Node中的事件循環(huán)分為多個(gè)階段,每個(gè)階段都有對(duì)應(yīng)的回調(diào)隊(duì)列,每次到達(dá)一個(gè)階段,會(huì)執(zhí)行隊(duì)列里的任務(wù)。

      當(dāng)隊(duì)列被清空或者執(zhí)行一定數(shù)量的任務(wù)后,則會(huì)進(jìn)入下一個(gè)階段。

      具體流程如下:

      詳細(xì)的總結(jié)可以看官方文檔:Node.js — The Node.js Event Loop (nodejs.org)

      或者可以看我之前寫的一篇博客:[NodeJS] NodeJS事件循環(huán) - feixianxing - 博客園 (cnblogs.com)

      graph TD; start-->timers; timers==>pending[pending callbacks]; pending==>idle[idle, prepare]; idle==>poll[poll callbacks]; poll==>check; check==>close[close callbacks]; close==>if[Any pending timers or I/O tasks?]; if-->|YES|timers; if-->|NO|exit[exit program]; incoming[incoming: connections, data, etc.]-.->poll

      對(duì)于剛開始嘗試使用NodeJS開發(fā)后端應(yīng)用的前端開發(fā)人員來說,使用NodeJS編寫服務(wù)端代碼有以下注意事項(xiàng):

      1. 在回調(diào)函數(shù)中使用fscryptozlib的API都應(yīng)該使用異步的,因?yàn)檫@時(shí)已經(jīng)進(jìn)入事件循環(huán)階段了,不能阻塞;而在頂層同步代碼的范圍內(nèi),則可以根據(jù)情況選擇同步或者異步API。

        案例:有一個(gè)接口,它的響應(yīng)與一個(gè)較大的文件有關(guān),而這個(gè)文件的內(nèi)容是不變的。假如每次請(qǐng)求都去異步地讀取這個(gè)文件內(nèi)容,然后再返回的話,其實(shí)很耗費(fèi)時(shí)間,可以考慮在啟動(dòng)服務(wù)器的時(shí)候就同步/異步的讀取文件內(nèi)容保存到一個(gè)變量里,后續(xù)每次請(qǐng)求只需要拿變量的數(shù)據(jù)就OK了(其實(shí)就是做了個(gè)緩存,不需要每次請(qǐng)求都去磁盤找內(nèi)容,在服務(wù)啟動(dòng)的時(shí)候就把內(nèi)容先讀到內(nèi)存了)。

      2. 不要執(zhí)行復(fù)雜的計(jì)算(即時(shí)間復(fù)雜度高的算法);

      3. 謹(jǐn)慎處理復(fù)雜對(duì)象的JSON序列化;

      4. 不要使用復(fù)雜的正則表達(dá)式;

      5. 將耗時(shí)任務(wù)卸載給線程池或者使用child.processes

      總結(jié):核心思想就是不要阻塞主線程,因?yàn)閬碜运杏脩舻乃姓?qǐng)求都通過主線程處理,一旦阻塞基本上服務(wù)就廢了。

      事件驅(qū)動(dòng)架構(gòu)

      NodeJS提供了一個(gè)events模塊,其中有一個(gè)類是EventEmitter,這個(gè)類是NodeJS事件驅(qū)動(dòng)架構(gòu)的核心,很多其它NodeJS的核心類都繼承了這個(gè)類。

      http模塊中的 server 就是繼承了EventEmitter,因此有相關(guān)的 on 方法:

      const server = http.createServer();
      server.on('request', (req, res)=>{
       console.log('Request received');
       res.end('Request received');
      });
      

      EventEmitter是基于發(fā)布/訂閱模式設(shè)計(jì)的:

      • 發(fā)布者Emitters通過emit方法發(fā)布指定名稱的事件;
      • 訂閱者Listeners通過on方法訂閱指定名稱的事件并注冊(cè)回調(diào)函數(shù)。

      簡(jiǎn)單地介紹發(fā)布/訂閱模式:發(fā)布者和訂閱者之間是松散耦合的,它們互相不知道對(duì)方的存在,僅通過中間的消息代理進(jìn)行通信。

      EventEmitter使用指南

      1. 限制監(jiān)聽器數(shù)量:一個(gè)事件如果有太多監(jiān)聽器會(huì)占用大量?jī)?nèi)存。可以使用 setMaxListeners 方法來控制最大監(jiān)聽器數(shù)量。

        const EventEmitter = require('events');
        const emitter = new EventEmitter();
        emitter.setMaxListeners(10); // 設(shè)置最大監(jiān)聽器數(shù)量為10
        
      2. 正確處理錯(cuò)誤:始終提供錯(cuò)誤監(jiān)聽器以捕獲和優(yōu)雅地處理錯(cuò)誤;如果沒有監(jiān)聽錯(cuò)誤事件,emit('error')會(huì)拋出異常,并打印調(diào)用堆棧,結(jié)束進(jìn)程。

      3. 移除不再使用的監(jiān)聽器:在不再需要時(shí)清理監(jiān)聽器,以釋放資源。

      4. 使用描述性的事件名稱:使用有意義且描述性的事件名稱,使代碼更加可讀和易于維護(hù)。

      參考

      [1] B站 NodeJS 教學(xué)視頻
      [2] Events | Node.js v22.4.0 Documentation
      [3] Node.js——The Node.js Event Loop
      [4] [NodeJS] NodeJS事件循環(huán) - feixianxing - 博客園
      [5] geeks for geeks: What is EventEmitter in Node.js ?

      posted @ 2024-07-08 13:53  feixianxing  閱讀(112)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 东方av四虎在线观看| 日韩精品卡一卡二卡三卡四| 2021国产在线视频| 巩留县| 亚洲女同在线播放一区二区| 人妻综合专区第一页| 中文字幕人妻日韩精品| 性色av一区二区三区v视界影院| 国产精品v片在线观看不卡| 欧美xxxxx在线观看| 国产男女黄视频在线观看| 亚洲欧洲一区二区综合精品| 久久中文字幕日韩无码视频| 久久精品国产精品亚洲综合| 亚洲国产精品久久久天堂麻豆宅男| 国产亚洲精品超碰热| 米易县| 午夜福利在线观看6080| 亚洲中文字幕无码爆乳| 亚洲AV无码专区亚洲AV紧身裤| 午夜福利免费视频一区二区| 中文字幕亚洲中文字幕无码码| 亚洲av精彩一区二区| 国产一级av在线播放| 国产不卡精品视频男人的天堂| 国精品午夜福利不卡视频| 成人午夜免费无码视频在线观看| 欧美三级欧美成人高清| 隆子县| 亚洲小说乱欧美另类| 无码中文av波多野结衣一区| 亚洲成aⅴ人在线观看| 亚洲最大福利视频网| 粗大的内捧猛烈进出小视频| 亚洲国产一区二区三区久| 国产综合色在线精品| 国产精品va在线观看无码不卡| 亚洲AV日韩AV永久无码电影| 人妻日韩精品中文字幕| 亚洲欧洲av一区二区| 97在线视频人妻无码|