摘要:概述本文主要介紹了我對(duì)的一些核心特性的理解,包括架構(gòu)特點(diǎn)機(jī)制核心模塊與簡(jiǎn)單應(yīng)用。在此期間,主線程繼續(xù)執(zhí)行其他任務(wù)。延續(xù)了瀏覽器端單線程,只用一個(gè)主線程執(zhí)行,不斷循環(huán)遍歷事件隊(duì)列,執(zhí)行事件。
原文地址在我的博客,轉(zhuǎn)載請(qǐng)注明來(lái)源,謝謝!
node是在前端領(lǐng)域經(jīng)常看到的詞。node對(duì)于前端的重要性已經(jīng)不言而喻,掌握node也是作為合格的前端工程師一項(xiàng)基本功了。知道node、知道后端的一些東西,才能更好的與別人合作,發(fā)揮更大的價(jià)值。
概述本文主要介紹了我對(duì)node的一些核心特性的理解,包括node架構(gòu)、特點(diǎn)、機(jī)制、核心模塊與簡(jiǎn)單應(yīng)用。
正文 從瀏覽器到node首先,node是一個(gè)平臺(tái),使用javascript作為編程語(yǔ)言,運(yùn)行在服務(wù)端。服務(wù)端語(yǔ)言能做的,node一般都能做,而且有些情況下做的更好,因?yàn)樗哂凶约旱奶厣?/p>
node是javascript運(yùn)行環(huán)境(runtime),就像瀏覽器一樣,是一個(gè)平臺(tái)。在瀏覽器中,V8引擎負(fù)責(zé)解釋javascript,你在javascript調(diào)用的接口都是瀏覽器實(shí)現(xiàn)并提供的,瀏覽器會(huì)調(diào)用底層的、由其他語(yǔ)言(C++)實(shí)現(xiàn)并封裝好的接口來(lái)完成任務(wù);同樣,在node中,也是V8引擎負(fù)責(zé)解釋javascript,而你在javascript調(diào)用的瀏覽器提供的接口就不能用了,因?yàn)樗撾x了瀏覽器的環(huán)境,但是因?yàn)槟阍趎ode環(huán)境中,你就可以使用node提供的由C++語(yǔ)言實(shí)現(xiàn)的、由javascript封裝好的各種接口來(lái)完成后端任務(wù)。瀏覽器提供的API用于處理前端任務(wù),比如彈個(gè)窗,換個(gè)主題,處理用戶操作等,而node因?yàn)榉?wù)后端,因此提供的API則用來(lái)處理后端任務(wù),比如響應(yīng)請(qǐng)求,讀取文件等,這些API由不同的模塊提供。因?yàn)殛P(guān)注領(lǐng)域不一樣,因此所做的任務(wù)就不一樣,提供的API就不一樣,但是原理、相關(guān)實(shí)現(xiàn)大致與瀏覽器端相同。
從瀏覽器到node這一塊如果想了解更多,推薦IBM的文章node.js到底是什么?
node 架構(gòu)node架構(gòu)分為三層(參考鏈接):
圖片來(lái)源
Node standard library:node標(biāo)準(zhǔn)庫(kù),也就是node模塊提供各種接口的javascript實(shí)現(xiàn),任何javascript代碼、npm install 或者你寫的模塊都在這里
Node bindings:包括C/C++ bindings(膠水代碼)和Add on(添加其他C/C++庫(kù)時(shí)需要自己寫的Bindings),這一層向下封裝了V8和libuv接口,向上提供了基礎(chǔ)API接口,是連接javascript和C++的橋梁
第三層是支撐 Node.js 運(yùn)行的關(guān)鍵,由 C/C++ 實(shí)現(xiàn)。
V8 是Google開發(fā)的JavaScript引擎,提供JavaScript運(yùn)行環(huán)境,可以說(shuō)它就是 Node.js 的發(fā)動(dòng)機(jī),負(fù)責(zé)解釋javascript,與chrome瀏覽器相同。
Libuv 是專門為Node.js開發(fā)的一個(gè)封裝庫(kù),提供跨平臺(tái)的異步I/O能力,負(fù)責(zé)node運(yùn)行時(shí)的線程池調(diào)度。
C-ares:提供了異步處理 DNS 相關(guān)的能力。
http_parser、OpenSSL、zlib 等:提供包括 http 解析、SSL、數(shù)據(jù)壓縮等系統(tǒng)底層的訪問。
平常我們用到的也就是第一層node各個(gè)模塊實(shí)現(xiàn)的接口。
那他們之間時(shí)如何協(xié)作的呢
程序啟動(dòng),V8引擎會(huì)首先解析javascript代碼,通過Node bindings來(lái)調(diào)用C/C++庫(kù)。執(zhí)行到當(dāng)前事件時(shí),會(huì)把事件放在調(diào)用堆棧(stack和heap)處理(可以理解為放進(jìn)一個(gè)工作空間,如上圖),在堆棧中的任何I/O請(qǐng)求都會(huì)交給libuv來(lái)處理,libuv維持一個(gè)線程池,里面是一些工作線程(如下圖),請(qǐng)求會(huì)調(diào)用這些線程來(lái)完成任務(wù),這些線程則調(diào)用底層的C/C++庫(kù)。完成時(shí),libuv再把結(jié)果返回事件隊(duì)列等待主線程執(zhí)行。在此期間,主線程繼續(xù)執(zhí)行其他任務(wù)。
node 執(zhí)行特性單線程的意思就是只在一個(gè)線程上運(yùn)行javascript。首先,javascript 在瀏覽器端是單線程的,這是為了避免多線程產(chǎn)生任務(wù)沖突的情況;其次,java和PHP這類多線程后端語(yǔ)言,為避免同步I/O阻塞,每處理一個(gè)連接都會(huì)產(chǎn)生一個(gè)新線程,這樣的話在遇到大量并發(fā)請(qǐng)求時(shí)就會(huì)受到物理內(nèi)存的限制。node 延續(xù)了瀏覽器端單線程javascript,只用一個(gè)主線程執(zhí)行javascript,不斷循環(huán)遍歷事件隊(duì)列,執(zhí)行事件。事實(shí)上,主線程發(fā)出的I/O請(qǐng)求,都會(huì)交給其他線程去完成,其他線程完成后悔返回結(jié)果放到事件隊(duì)列。在此期間,主線程會(huì)繼續(xù)執(zhí)行其他任務(wù),也就是在交給libuv后直接返回,繼續(xù)執(zhí)行下面的任務(wù),主線程只負(fù)責(zé)循環(huán)執(zhí)行事件隊(duì)列,因此這種模式稱為非阻塞型I/O,性能很好,適用于處理大量并發(fā)請(qǐng)求,還能簡(jiǎn)化開發(fā)。
還是跟瀏覽器的差不多。總的來(lái)說(shuō)就是,瀏覽器端把鼠標(biāo)點(diǎn)擊、鍵盤按鍵等定義為事件,而node把網(wǎng)絡(luò)請(qǐng)求、I/O操作等也看作事件,嚴(yán)格來(lái)說(shuō),一切動(dòng)作都是事件,這就是事件驅(qū)動(dòng)的思想。在程序啟動(dòng)時(shí),便進(jìn)入事件循環(huán),不斷遍歷執(zhí)行事件隊(duì)列中產(chǎn)生的事件,而在執(zhí)行過程中,又會(huì)產(chǎn)生新的事件,因此稱為事件循環(huán)。主線程執(zhí)行事件時(shí),遇到麻煩的I/O請(qǐng)求會(huì)交給libuv來(lái)調(diào)度其他工作線程來(lái)幫忙,忙完后就會(huì)形成事件返回結(jié)果到事件隊(duì)列等待主線程處理。在此期間,主線程會(huì)繼續(xù)執(zhí)行其他任務(wù)。
mbp 曾經(jīng)做過一個(gè)巧妙的比喻,把 Node.js 看成一家餐廳。我在此借用下他的例子,稍作修改來(lái)闡述下 Node.js 的執(zhí)行情況:
把 Node.js 應(yīng)用程序想象成一家星巴克,一個(gè)訓(xùn)練有素的前臺(tái)服務(wù)生(唯一的主線程)在柜臺(tái)前接受訂單。當(dāng)很多顧客同時(shí)光臨的時(shí)候,他們排隊(duì)(進(jìn)入事件隊(duì)列)等候接待;每當(dāng)服務(wù)生接待一位顧客,服務(wù)生會(huì)把訂單告知給經(jīng)理(libuv),經(jīng)理安排相應(yīng)的專職人員去烹制咖啡(工作線程或者系統(tǒng)特性)。這個(gè)專職人員會(huì)使用不同的原料和咖啡機(jī)(底層 C/C++ 組件)按訂單要求制作咖啡或甜點(diǎn),通常會(huì)有四個(gè)這樣的專職人員保持在崗待命(線程池),高峰期的時(shí)候也可以安排更多(不過需要在一早就安排人員來(lái)上班,而不能中午臨時(shí)通知)。服務(wù)生把訂單轉(zhuǎn)交給經(jīng)理之后不需要等著咖啡制作完成,而是直接開始接待下一位顧客(事件循環(huán)放進(jìn)調(diào)用堆棧的另一個(gè)事件),你可以把當(dāng)前調(diào)用堆棧里的事件看成是站在柜臺(tái)前正在接受服務(wù)的顧客。
當(dāng)咖啡完成時(shí),會(huì)被發(fā)送到顧客隊(duì)列的最后位置,等它移動(dòng)到柜臺(tái)前服務(wù)生會(huì)叫相應(yīng)顧客的名字,顧客就來(lái)取走咖啡(最后這部分在真實(shí)生活中聽起來(lái)有點(diǎn)怪,不過你從程序執(zhí)行的角度理解就比較合乎情理了)。
? ——By Amio
如果你想進(jìn)一步了解javascript 事件驅(qū)動(dòng)機(jī)制,推薦深入理解 javascript 事件循環(huán)機(jī)制
node 模塊node 模塊機(jī)制是CommonJs 的實(shí)現(xiàn)。起初,javascript 標(biāo)準(zhǔn)一片混沌,并沒有其他成熟語(yǔ)言(例如C++)的模塊機(jī)制、標(biāo)準(zhǔn)庫(kù)、接口等,為了讓javascript 具備開發(fā)大型應(yīng)用的能力,為了讓 javascript 能在后端運(yùn)行,CommonJS 就制定了javascript 模塊規(guī)范。node 借鑒了這個(gè)規(guī)范,讓javascript 以模塊形式組織起來(lái)。模塊機(jī)制是一個(gè)成熟語(yǔ)言必備的,一個(gè)模塊代表一個(gè)功能的封裝,它就像搭積木一樣,不同模塊可以銜接在一塊,使語(yǔ)言具有極強(qiáng)的可擴(kuò)展型。node 模塊機(jī)制同時(shí)制定了模塊規(guī)范,能讓全球的開發(fā)者都可以在node官網(wǎng)上傳自己的包。此外,node 社區(qū)又實(shí)現(xiàn)了node 包管理器npm,使用npm可以輕松管理各種包。
node 的模塊分為核心模塊和用戶模塊,前者是底層的、自帶的,后者是第三方。
核心模塊有Global(全局對(duì)象)、Http、fs(文件系統(tǒng))、Buffer、Stream、Events、URL、path等,這些模塊提供了后端服務(wù)的基本功能,都提供自己關(guān)注功能的API。
在使用模塊時(shí),require 即可。但在require背后,node 有一套尋找模塊的機(jī)制:
從上圖可以看到,node 優(yōu)先從緩存區(qū)讀取,緩存區(qū)有直接讀取,沒有則加載并緩存,這樣做不用一遍一遍去找了,非常高效。node 在緩存區(qū)沒有發(fā)現(xiàn)模塊時(shí),會(huì)分析require 的路徑和文件后綴,node 有個(gè)模塊路徑的查找策略,我們可以在名為module_paths 的js文件里console.log(module.paths)然后node module_paths.js 運(yùn)行來(lái)間接查看node 尋找文件模塊的具體文件的方式:
[ "/home/username/nodeProject/node_modules", "/home/username/node_modules", "/home/node_modules", "/node_modules" ] //Linux下的數(shù)組輸出(/home/username因電腦不同而異) [ "c: odeProject ode_modules", "c: ode_modules" ] //Windows
也就是按照下面的順序:
當(dāng)前文件目錄下的node_modules目錄。
父目錄下的node_modules目錄。
父目錄的父目錄下的node_modules目錄。
沿路徑向上逐級(jí)遞歸,直到根目錄下的node_modules目錄。
這些順序都是在查找緩存之后的。
在找到模塊后,node 將在引入之前對(duì)這個(gè)模塊進(jìn)行編譯執(zhí)行,編譯成功后會(huì)緩存,執(zhí)行的結(jié)果會(huì)返回給調(diào)用者。
簡(jiǎn)單應(yīng)用有了node 自帶核心模塊的基礎(chǔ)功能,就可以進(jìn)一步封裝更強(qiáng)大、容易操作的功能了,就像jQuery 對(duì)于javascript 基礎(chǔ)API 一樣,node 社區(qū)也誕生了像 Express、KOA等框架來(lái)構(gòu)建node.js程序
這些框架的詳情移步2017 Node.js 開發(fā)框架比較
另外,node 還可以連接MySQL,MangoDB進(jìn)行數(shù)據(jù)庫(kù)操作。
下面是使用express 腳手架生成的基本 node應(yīng)用結(jié)構(gòu):
. ├── app.js //程序入口 ├── bin │ └── www //二機(jī)制文件 ├── package.json //項(xiàng)目配置文件 ├── public │ ├── images │ ├── javascripts │ └── stylesheets │ └── style.css ├── routes │ ├── index.js //路由文件入口 │ └── users.js └── views ├── error.jade //界面模板 ├── index.jade └── layout.jade
現(xiàn)在使用 node作為后端語(yǔ)言通常都要配合類庫(kù)和框架使用。
node 的單線程、非阻塞型特點(diǎn)讓它非常適合高并發(fā)的應(yīng)用,適合處理大量重復(fù)的、簡(jiǎn)單的邏輯,適合構(gòu)建Rest/JSON API服務(wù);同時(shí),也正是因?yàn)檫@些特性,node 不適合CPU使用率較重、IO使用率較輕的偏計(jì)算應(yīng)用。缺點(diǎn)是因?yàn)閱尉€程,一個(gè)進(jìn)程掛就全掛了,可靠性低,但這是可以避免的。node 更多的應(yīng)用是在前端、中間件、前后端分離等。
由于 node 的諸多優(yōu)點(diǎn),現(xiàn)在越來(lái)越多大公司開始使用node、深度使用node。
總結(jié)node 的核心概念、思想遠(yuǎn)不止這么多,應(yīng)用更是多了去了,無(wú)奈本人水平有限,只能說(shuō)個(gè)淺層,還有很多像進(jìn)程管理、異步編程、異常調(diào)試、部署、性能調(diào)優(yōu)、與集群、CDN協(xié)調(diào)等都值得深入探索一下。無(wú)論如何,node 是讓javascript 邁向企業(yè)級(jí)開發(fā)語(yǔ)言重要的一步(也許已經(jīng)是了),前端工程師從未像現(xiàn)在這樣的powerful,能做的事情越來(lái)越多,所能涉及的領(lǐng)域也越來(lái)越多。前端這行越來(lái)越令人興奮了。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/89064.html
摘要:是一個(gè)針對(duì)網(wǎng)絡(luò)應(yīng)用開發(fā)的平臺(tái)它基于的運(yùn)行時(shí)引擎但它不僅僅只是的標(biāo)準(zhǔn)類庫(kù)是它非常重要的一部分它涵蓋了從服務(wù)端到同步或者異步的文件管理已經(jīng)迅速成為一個(gè)可行并且真正高效的開發(fā)平臺(tái)在誕生之前在服務(wù)端運(yùn)行是件不可思議的事情并且對(duì)其他腳本語(yǔ)言來(lái)說(shuō)要實(shí)現(xiàn) Node是一個(gè)針對(duì)網(wǎng)絡(luò)應(yīng)用開發(fā)的平臺(tái),它基于Google的JavaScript運(yùn)行時(shí)引擎V8,但它不僅僅只是V8.Node的標(biāo)準(zhǔn)類庫(kù)是它非常重要的...
摘要:本文將根據(jù)以下章節(jié)分別梳理每個(gè)鉤子同步鉤子首先安裝是簡(jiǎn)單的同步鉤子,它很類似于發(fā)布訂閱。至此,我們把的所有同步鉤子都解析完畢異步鉤子比同步鉤子麻煩些,我們會(huì)在下一章節(jié)開始解析異步的鉤子傳送門深入理解核心模塊鉤子異步版代碼 記錄下自己在前端路上爬坑的經(jīng)歷 加深印象,正文開始~ tapable是webpack的核心依賴庫(kù) 想要讀懂webpack源碼 就必須首先熟悉tapableok.下面是...
摘要:感謝大神的免費(fèi)的計(jì)算機(jī)編程類中文書籍收錄并推薦地址,以后在倉(cāng)庫(kù)里更新地址,聲音版全文狼叔如何正確的學(xué)習(xí)簡(jiǎn)介現(xiàn)在,越來(lái)越多的科技公司和開發(fā)者開始使用開發(fā)各種應(yīng)用。 說(shuō)明 2017-12-14 我發(fā)了一篇文章《沒用過Node.js,就別瞎逼逼》是因?yàn)橛腥嗽谥跎虾贜ode.js。那篇文章的反響還是相當(dāng)不錯(cuò)的,甚至連著名的hax賀老都很認(rèn)同,下班時(shí)讀那篇文章,竟然坐車的還坐過站了。大家可以很...
摘要:感謝大神的免費(fèi)的計(jì)算機(jī)編程類中文書籍收錄并推薦地址,以后在倉(cāng)庫(kù)里更新地址,聲音版全文狼叔如何正確的學(xué)習(xí)簡(jiǎn)介現(xiàn)在,越來(lái)越多的科技公司和開發(fā)者開始使用開發(fā)各種應(yīng)用。 說(shuō)明 2017-12-14 我發(fā)了一篇文章《沒用過Node.js,就別瞎逼逼》是因?yàn)橛腥嗽谥跎虾贜ode.js。那篇文章的反響還是相當(dāng)不錯(cuò)的,甚至連著名的hax賀老都很認(rèn)同,下班時(shí)讀那篇文章,竟然坐車的還坐過站了。大家可以很...
閱讀 1383·2021-11-04 16:11
閱讀 3043·2021-10-12 10:11
閱讀 2975·2021-09-29 09:47
閱讀 1615·2021-09-22 15:40
閱讀 1013·2019-08-29 15:43
閱讀 2804·2019-08-29 13:50
閱讀 1579·2019-08-29 13:28
閱讀 2691·2019-08-29 12:54