摘要:而通過實(shí)現(xiàn)名為的標(biāo)準(zhǔn)模塊,完美的解決了模塊導(dǎo)入問題。通常都被稱為包管理器,而這也是它最大的特色。例如,接受請求發(fā)送響應(yīng)。該模塊主要處理文件相關(guān)內(nèi)容,其中大多數(shù)都是文件讀寫功能。
在上一篇文章中,我們簡單的介紹了 Node.js 。了解到它基于 JavaScript、天生異步、擁有大量的第三方類庫。本文將會(huì)在之前的基礎(chǔ)上,對 Node.js 進(jìn)行更深入的介紹。其中主要內(nèi)容包括:
Node 的安裝
如何使用第三方模塊生態(tài)
第三方模塊的安裝
一些簡單的使用示例
開發(fā)過程中的一些建議和技巧
在此之前,我假設(shè)你已經(jīng)掌握了 JavaScript 基礎(chǔ)知識并且熟悉一些基本的命令行操作。另外,不要臆想通過這一章就全面掌握 Node。但是如果你有心的話,可以去閱讀 Node.js 實(shí)戰(zhàn)。
安裝NodeJavaScript 世界的一大特點(diǎn)就是它選擇性非常多,Node 的安裝也不例外。
可以在官方下載頁面找到各種版本的源代碼和安裝包文件。建議你使用與自己操作系統(tǒng)對應(yīng)的安裝包進(jìn)行安裝。當(dāng)然,你也可用使用 apt-get、Homebrew 等包管理器進(jìn)行安裝,如果你系統(tǒng)有的話。具體詳見官方的包管理工具的安裝指南。
如果你使用的是 Mac 或者 Linux 的話,那么我極力推薦你使用 NVM 來安裝。Window 系統(tǒng)上的對應(yīng)程序是 NVMW。這些版本管理工具,讓你可以在不同版本間進(jìn)行自由切換。例如,你可以在嘗試新版本的特性時(shí),同時(shí)在系統(tǒng)中保留一份穩(wěn)定版。另外,NVM 無需系統(tǒng)管理權(quán)限同時(shí)卸載也非常容易。而安裝過程也只需在終端執(zhí)行一行命令。
現(xiàn)在,請?jiān)谀阆到y(tǒng)中安裝好 Node。
運(yùn)行你的第一個(gè)Node腳本安裝完成后,先動(dòng)手寫個(gè) "Hello World" 來檢驗(yàn)一些。在新建的 helloworld.js 中加入一下代碼:
console.log("Hello, World!");
代碼中主要就是使用 console.log 來打印字符串 "Hello,world!",相信對于前端程序員來說并不會(huì)感到陌生。下面我們使用 node helloworld.js 運(yùn)行代碼。如果一切正常的話,會(huì)出現(xiàn)如下輸出:
模塊的使用在大多數(shù)編程語言中,我們都會(huì)對代碼進(jìn)行拆分,然后在使用的時(shí)候?qū)⑦@些文件引入其中。例如,C 和 C++ 中的 include,Python 的 import ,Ruby 和 PHP 中的 require。而另外一些語言,如 C# 是在編譯時(shí)完成跨文件引用的。
很長一段時(shí)間內(nèi),JavaScript 官方并不支持模塊機(jī)制。所以社區(qū)中有人就編寫了 RequireJS 這種工具來解決依賴項(xiàng)導(dǎo)入的問題。但是,大多數(shù)時(shí)候還是通過 標(biāo)簽來進(jìn)行文件導(dǎo)入。而Node 通過實(shí)現(xiàn)名為 CommonJS 的標(biāo)準(zhǔn)模塊,完美的解決了模塊導(dǎo)入問題。
模塊系統(tǒng)部分主要有三大主要內(nèi)容:內(nèi)置模塊的引入,第三方模塊引入,個(gè)人私有模塊引入。下面,將會(huì)對這些內(nèi)容逐一介紹。
引入內(nèi)置模塊Node 已經(jīng)內(nèi)置了很多實(shí)用模塊,例如,文件系統(tǒng)模塊 fs,工具函數(shù)模塊 util。
在 Node 編寫的 Web 應(yīng)用中,最常見的任務(wù)當(dāng)屬 URL 解析了。瀏覽器通過特定的 URL 來請求服務(wù)器上對應(yīng)的資源。例如,訪問主頁、訪問關(guān)于頁面 的網(wǎng)絡(luò)請求。這些 URL 都以字符串的形式存在,我們需要對其進(jìn)行解析然后獲取更多的信息。這里我們通過對 URL 進(jìn)行解析來介紹如何引入內(nèi)置模塊。
內(nèi)置的 url 模塊中暴露的方法不多,不過其中有一個(gè) parse 函數(shù)非常有用。它能從 URL 字符串中提取到類似域名和路徑等有益信息。
這里我們使用 require 來實(shí)現(xiàn)模塊導(dǎo)入,該命令與之前提到的 Include、Import 的作用一致。通過將模塊名作為參數(shù),該命令就能成功的返回對應(yīng)的模塊。大多數(shù)情況下,該返回的對象是一個(gè) object 對象,但有時(shí)也可能會(huì)是字符串、數(shù)字、或者函數(shù)。下面是引入改模塊的示例代碼:
var url = require("url");?? var parsedURL = url.parse("http://www.example.com/profile?name=barry");? ? console.log(parsedURL.protocol);? // "http:" console.log(parsedURL.host);????? // "www.example.com" console.log(parsedURL.query);???? // "name=barry
在上面的代碼中,通過 require("url") 返回一個(gè)模塊對象,然后就可以像使用其他對象一樣調(diào)用對象的方法。將這段代碼保存到 url-test.js 中并使運(yùn)行 node url-test.js 命令,你就會(huì)看到協(xié)議名,域名、查詢條件。
另外,絕大多數(shù)時(shí)候我們在引入模塊的時(shí)候會(huì)用一個(gè)同名的變量來接受返回的模塊對象。例如,上面就使用 url 來介紹 require("url") 的返回值。當(dāng)然,你完全可以不遵循上面的規(guī)則。如果你想的話,你也可以這么干:
var theURLModule = require("url");?? var parsedURL = theURLModule.parse("http://www.example.com/profile?name=barry");?
保存變量名和模塊名一致只是一個(gè)統(tǒng)一風(fēng)格增加可讀性的寬松約定,而不是什么強(qiáng)制規(guī)范。
使用 npm 和 package.json 引入第三方模塊Node 的內(nèi)置模塊遠(yuǎn)遠(yuǎn)不能滿足日常開發(fā)需要,所以引入第三方模塊是一個(gè)必須要掌握的技能。
首先,我們需要了解 package.json 文件。所有的 Node 項(xiàng)目都多帶帶存放在一個(gè)文件夾中,而項(xiàng)目如果使用了第三方模塊,那么其中必定存在一個(gè)名為 package.json 的文件。package.json 中的內(nèi)容非常的簡單,一般其中定義了項(xiàng)目名稱、版本號、作者,已經(jīng)項(xiàng)目的外部依賴項(xiàng)。
在新建的 Node 工程文件夾中,將下面的內(nèi)容復(fù)制到 package.json 中。
{ ? "name": "my-fun-project",?? ? "author": "Evan Hahn",????? ? "private": true,??????????? ? "version": "0.2.0",???????? ? "dependencies": {}????????? }
其實(shí),在進(jìn)行 Node 安裝時(shí)實(shí)際上還安裝了另一個(gè)程序:npm 。通常 npm 都被稱為 Node 包管理器,而這也是它最大的特色。假設(shè),現(xiàn)在需要在應(yīng)用中導(dǎo)入一個(gè)小型的標(biāo)準(zhǔn)模版系統(tǒng) Mustache。它能將模版字符串轉(zhuǎn)化為真正的字符串,請看代碼:
// Returns "Hello, Nicholas Cage!" Mustache.render("Hello, {{first}} {{last}}!", { ? first: "Nicholas", ? last: "Cage" }); ? // Returns "Hello, Sheryl Sandberg!" Mustache.render("Hello, {{first}} {{last}}!", { ? first: "Sheryl", ? last: "Sandberg" });
現(xiàn)在,假設(shè)你想通過 Mustache 模塊來編寫一個(gè)簡單的 Node 應(yīng)用來歡迎 Nicolas Cage。
首先,在工程文件夾的根目錄里運(yùn)行 npm install mustache --save 。該命令會(huì)新建一個(gè) node_modules 文件夾并將 Mustache 保存到文件夾下。 --save 參數(shù)將會(huì)把該模塊添加到 pakage.json 文件中。此時(shí) pakage.json 文件夾大致如下,其中 Mustache 會(huì)使用最新的版本。
{ ? "name": "my-fun-project", ? "author": "Evan Hahn", ? "private": true, ? "version": "0.2.0", ? "dependencies": { ??? "mustache": "^2.0.0"? #A ? } }
如果你沒有使用 --save 選項(xiàng)的話,雖然也會(huì)創(chuàng)建 node_modules 文件夾將把 Mustache 模塊保存到同名子目錄下,但是 pakage.json 將不會(huì)發(fā)生任何變化。這里之所以將這些依賴關(guān)系保存到 package.json 是為了方便其他開發(fā)者在得到工程后直接使用 npm install 完成所有依賴項(xiàng)的安裝。另一個(gè)原因是 Node 項(xiàng)目在進(jìn)行代碼管理時(shí)通常都會(huì)忽略 node_modules 文件夾而只保留 package.json。
安裝完成后接下來就是使用了:
var Mustache = require("mustache");? var result = Mustache.render("Hi, {{first}} {{last}}!", { ? first: "Nicolas", ? last: "Cage" }); console.log(result);
保存代碼到 mustache-test.js 中并執(zhí)行 node mustache-test.js 命令。然后你將會(huì)看見 Hi,Nicolas Cage! 。
就是這樣簡單,這些依賴項(xiàng)安裝完成后,你可以像使用內(nèi)置模塊一樣進(jìn)行調(diào)用。node_modules 中模塊引入的工作直接交給 Node 就行了,你無需擔(dān)心。
當(dāng)然你可以手動(dòng)添加工程依賴項(xiàng),并且你還可以指定依賴項(xiàng)的版本。
實(shí)現(xiàn)私有模塊npm init
除了安裝依賴項(xiàng)之外,npm 還能完成其他任務(wù)。例如,自動(dòng)生成 package.json 而不是通過手動(dòng)編輯的方式。在一個(gè)新工程的文件夾中可以通過 npm init 來配置工程名、作者、版本等信息,然后 npm 就會(huì)自定生成對應(yīng)的 package.json 文件。這種自動(dòng)化過程可以節(jié)約開發(fā)者的時(shí)間。
前面都是介紹如何使用他人開發(fā)好的模塊,接下來你將會(huì)學(xué)到如何去開發(fā)一個(gè)私有模塊。假設(shè)現(xiàn)在需要隨機(jī)返回 0 ~ 100 之間的整數(shù)。在不引入其他模塊的情況下,代碼大致如下:
var MAX = 100; function randomInteger() { return Math.floor( (Math.random() * MAX) ); }
這可能與你在瀏覽器環(huán)境下代碼差不多,并沒有什么特別之處。但是在 Node 中,我們還需要暴露一個(gè)變量給外部使用。這樣當(dāng)其他程序在通過 require 進(jìn)行引入的時(shí)候就能獲得該變量。此例中,我們暴露函數(shù) randomInteger 并將代碼保存到 random-integer.js 文件中。
var MAX = 100; function randomInteger() { return Math.floor( (Math.random() * MAX) ); } module.exports = randomInteger;
最后一行代碼對于 Node 初學(xué)者來說可能感覺有點(diǎn)陌生。每個(gè)模塊只能暴露一個(gè)變量,而且必須通過 module.exports 設(shè)置。本例中只暴露了一個(gè)函數(shù)變量,所以 MAX 就作為模塊私有變量無法被其他文件所訪問。
module.exports 可以暴露任何變量,雖然本例中是一個(gè)函數(shù),但是通常都會(huì)是一個(gè)對象。當(dāng)然,你可以暴露字符串或者數(shù)組。
接下來我們就來使用一下這個(gè)新模塊。在 random-integer.js 同一目錄下,新建一個(gè) print-three-random-integers.js 并復(fù)制下面的代碼:
var randomInt = require("./random-integer");? #A console.log(randomInt());? // 12 console.log(randomInt());? // 77 console.log(randomInt());? // 8
除了需要通過點(diǎn)語法指定相對路徑之外,其余部分與前面幾乎一摸一樣。通過 node print-three-random-integers.js 命令,我們可以檢查程序的運(yùn)行效果。不出意外的話,將會(huì)有三個(gè) 0 ~ 100 之間的隨機(jī)數(shù)會(huì)被打印出來。
如果你嘗試運(yùn)行 node random-integer.js 的話,你還發(fā)現(xiàn)并沒有任何事情發(fā)生。雖然,我們暴露了模塊中的函數(shù),但是改函數(shù)并不會(huì)執(zhí)行更不會(huì)打印任何輸出。
注意,這里只涉及了私有模塊在工程中的使用。如果你希望將自己的模塊發(fā)布出去供其他人使用的話,可以去我的個(gè)人站點(diǎn)查看相關(guān)內(nèi)容。
以上部分就是 Node 模塊系統(tǒng)的簡單入門。
Node:異步的世界在第一章中,我用 “烤松餅” 的例子簡單的介紹了 Node 中的異步特性。其中的關(guān)鍵點(diǎn)就是,你無法同時(shí)做兩件事哪怕它們是同時(shí)發(fā)生的。雖然,在烘焙過程中我可以健身,但是,烤箱畢竟只是個(gè)外部事物。
Node 的異步工作原理與此類似,例如,你通過瀏覽器請求 Node 服務(wù)器上的一張小貓圖片。因?yàn)樵搱D片資源太大,所以在進(jìn)行磁盤讀寫的時(shí)候你可以抽身去處理其他事情。此時(shí),這個(gè)磁盤就相當(dāng)于一個(gè)外部資源,我們可以直接處理第二個(gè)請求而無需掛起等待費(fèi)時(shí)操作結(jié)束。
Express 中主要有兩個(gè)外部資源:
涉及文件系統(tǒng)。例如,磁盤文件的讀寫。
涉及網(wǎng)絡(luò)處理。例如,接受請求、發(fā)送響應(yīng)。
在 Node 代碼中,這些異步都是通過回調(diào)進(jìn)行處理的。其工作原理和在 Web 頁面發(fā)送 AJAX 請求一樣。在發(fā)送請求時(shí)你會(huì)附帶一個(gè)回調(diào)函數(shù),當(dāng)請求處理完成后你的回調(diào)將會(huì)被執(zhí)行。
例如,現(xiàn)在你正在硬盤上讀取文件 myfile.txt 。當(dāng)讀取結(jié)束后,你希望能夠打印出其中字母 X 出現(xiàn)的次數(shù),代碼如下:
var fs = require("fs");? ? var options = { encoding: "utf-8" };????????????????????? fs.readFile("myfile.txt", options, function(err, data) {? ? if (err) {???? ??????????????????????????? ??? console.error("Error reading file!");?? ??? return;???????????????????????????????? ? }???????????????????????????????????????? ? ? console.log(data.match(/x/gi).length + " letter X"s");?? });
下面我們一步步解釋這些代碼:
首先,我們導(dǎo)入 Node 自帶的文件系統(tǒng)模塊。該模塊主要處理文件相關(guān)內(nèi)容,其中大多數(shù)都是文件讀寫功能。本例使用的其中的 readFile 方法。
接下來,我們需要設(shè)置 fs.readFile 方法中的參數(shù),第一個(gè)是文件名,第二個(gè)就是會(huì)回調(diào)函數(shù)。并且在讀取結(jié)束后執(zhí)行回調(diào)函數(shù)。
在 Node 中大多數(shù)回調(diào)函數(shù)都會(huì)設(shè)置錯(cuò)誤信息 error 作為第一個(gè)參數(shù)。正常情況下該參數(shù)等于 null ,如果出現(xiàn)錯(cuò)誤則該參數(shù)會(huì)保存錯(cuò)誤信息。雖然有時(shí)候這些錯(cuò)誤信息并不會(huì)導(dǎo)致程序終止執(zhí)行,但是多數(shù)情形下我們都需要對錯(cuò)誤做出響應(yīng),例如,拋出異常并跳出回調(diào)函數(shù)。這也是 Node 中最常見的回調(diào)實(shí)踐。
最后,當(dāng)一切正常時(shí)我們使用正則表達(dá)式匹配字母 X 并打印其數(shù)量。
下面我們就來做個(gè)測試。這里,我們在上面代碼的結(jié)束加上一段,那么會(huì)發(fā)生什么事情呢?
var fs = require("fs");? ? var options = { encoding: "utf-8" };????????????????????? fs.readFile("myfile.txt", options, function(err, data) {? ? if (err) {???? ??????????????????????????? ??? console.error("Error reading file!");?? ??? return;???????????????????????????????? ? }???????????????????????????????????????? ? ? console.log(data.match(/x/gi).length + " letter X"s");?? }); console.log("Hello World!");
異步文件讀取時(shí)異步操作,所以這里先打印出來的是 " Hello world! ",然后才是異步函數(shù)中的打印操作。
這就是異步模式強(qiáng)大的地方。當(dāng)一個(gè)外部設(shè)備在處理費(fèi)時(shí)操作時(shí),你可以繼續(xù)運(yùn)行其他代碼。在 Web 應(yīng)用中這意味著相同的時(shí)間可以處理更多的請求。
用 Node 構(gòu)建 Web 服務(wù):http 模塊注意:如果你想了解更多 JavaScript 異步的內(nèi)容的話,你可以去油管上查看這個(gè)視頻。視頻中的講解同時(shí)適用于 Node 和瀏覽器環(huán)境。
只有理解了上面那些概念,你才能更好的掌握 Node 內(nèi)置的 HTTP 模塊。而該模塊對 Express 框架來說又是最重要的模塊之一。Node 和 Express 能夠構(gòu)建 Web 服務(wù)正是依賴于這個(gè)模塊中的功能。
Node 的 HTTP 模塊有很多特性(比如,向其他服務(wù)器發(fā)送網(wǎng)絡(luò)請求),不過我們將要使用的是其中一個(gè)名為 http.createServer 的方法。該方法通過其回調(diào)函數(shù)來處理每一次的網(wǎng)絡(luò)請求,并且進(jìn)行響應(yīng)。下面代碼中我們將所有的響應(yīng)都設(shè)置為了 "hello world" (可以保存到 myserver.js 中)。
var http = require("http");?????????? ? function requestHandler(request, response) {???????????? ? console.log("In comes a request to: " + request.url);? ? response.end("Hello, world!");???????????????????????? }?????????????????????????????? ????????????????????????? ? var server = http.createServer(requestHandler);? server.listen(3000);?
上面的代碼由 4 個(gè)部分構(gòu)成。
首先,我們引入 HTTP 模塊并將其保存到變量 http 中。這與之前 URL 模塊的操作一致。
接著,定義了一個(gè)請求處理函數(shù) requestHandler 。教程中的幾乎所有的代碼要么是請求處理函數(shù)要么是調(diào)用處理函數(shù)。該函數(shù)有兩個(gè)參數(shù),request 表示請求對象,而 response 則表示響應(yīng)對象。request 中包含 URL 路徑、user-agent 等信息。而通過調(diào)用 response 對象方法 Node 會(huì)將響應(yīng)信息打包好并發(fā)送給請求者。
余下的代碼則是指定內(nèi)置的 HTTP 服務(wù)在請求是執(zhí)行的處理函數(shù)以及服務(wù)監(jiān)聽的端口號。
對于 HTTPS 來說,我們則可以使用自帶的 HTTPS 模塊。除了需要配置 SSL 證書,其余的過程都一樣。如果你了解 HTTPS 的話那么后期從 HTTP 切換到 HTTPS 兩分鐘就能搞定。即使你不了解,也不必太過擔(dān)心。
如果你將代碼保存到 myserver.js 并執(zhí)行 node myserver.js 拉起服務(wù)。那么,此時(shí)你在瀏覽器中訪問 http://localhost:3000 ,你就會(huì)看到:
你可能也注意到了,每當(dāng)你發(fā)起請求的時(shí)候終端控制臺(tái)都會(huì)打印一些信息。當(dāng)你嘗試訪問不同 URL 時(shí),雖然控制臺(tái)打印的信息不同但是得到的響應(yīng)卻都是 “Hello, world!”。控制臺(tái)打印的信息類似于:
請注意上面打印的 URL 信息中并不包含 localhost:3000。雖然看起來顯得不那么直觀,但是反過來這也是對的。畢竟使用相對路徑,我們無需修改就能在任何電腦上部署 Node 應(yīng)用。
而 URL 解析的代碼大致如下:
function requestHandler(req, res) { if (req.url === "/") { res.end("Welcome to the homepage!"); } else if (req.url === "/about") { res.end("Welcome to the about page!"); } else { res.end("Error! File not found."); } }
所有的請求 URL 都可以在這個(gè)函數(shù)里面完成處理。這樣做對于簡單的應(yīng)用來說確實(shí)非常簡單,但是當(dāng)應(yīng)用規(guī)模變大之后該函數(shù)就會(huì)變的臃腫不利于維護(hù)。這也是 Express 框架出現(xiàn)的重要原因。
總結(jié)本文主要內(nèi)容:
Node 的安裝
模塊系統(tǒng)的使用
package.json 文件的介紹
通過 package.json 安裝第三放模塊依賴項(xiàng)
Node 中的異步編程概念。
簡單 HTTP 服務(wù)應(yīng)用的創(chuàng)建。
原文地址
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/84827.html
摘要:面向?qū)ο笕筇卣骼^承性多態(tài)性封裝性接口。第五階段封裝一個(gè)屬于自己的框架框架封裝基礎(chǔ)事件流冒泡捕獲事件對象事件框架選擇框架。核心模塊和對象全局對象,,,事件驅(qū)動(dòng),事件發(fā)射器加密解密,路徑操作,序列化和反序列化文件流操作服務(wù)端與客戶端。 第一階段: HTML+CSS:HTML進(jìn)階、CSS進(jìn)階、div+css布局、HTML+css整站開發(fā)、 JavaScript基礎(chǔ):Js基礎(chǔ)教程、js內(nèi)置對...
摘要:面向?qū)ο笕筇卣骼^承性多態(tài)性封裝性接口。第五階段封裝一個(gè)屬于自己的框架框架封裝基礎(chǔ)事件流冒泡捕獲事件對象事件框架選擇框架。核心模塊和對象全局對象,,,事件驅(qū)動(dòng),事件發(fā)射器加密解密,路徑操作,序列化和反序列化文件流操作服務(wù)端與客戶端。 第一階段: HTML+CSS:HTML進(jìn)階、CSS進(jìn)階、div+css布局、HTML+css整站開發(fā)、 JavaScript基礎(chǔ):Js基礎(chǔ)教程、js內(nèi)置對...
摘要:多一個(gè)技能多一條出路,祝你在自學(xué)道路上越走越好,掌握自己的核心技能,不只是優(yōu)秀,還要成為不可替代的人 NodeJs+Express+Mysql + Vuejs 項(xiàng)目實(shí)戰(zhàn) 最近準(zhǔn)備寫一系列文章,全面講述如何基于NodeJs + Express + Mysql + Vuejs 從零開發(fā)前后端完全分離項(xiàng)目; 文筆及技術(shù)可能在某些方面欠佳,請您指正,共同學(xué)習(xí)進(jìn)步 前端:Vuejs全家桶 后端:...
閱讀 3564·2023-04-26 02:05
閱讀 2003·2021-11-19 11:30
閱讀 4202·2021-09-30 09:59
閱讀 3175·2021-09-10 10:51
閱讀 2605·2021-09-01 10:30
閱讀 1470·2021-08-11 11:20
閱讀 2615·2019-08-30 15:54
閱讀 563·2019-08-30 10:49