欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:Node.js---菜鳥教程

柚子快報激活碼778899分享:Node.js---菜鳥教程

http://yzkb.51969.com/

文章目錄

創(chuàng)建第一個應(yīng)用創(chuàng)建 Node.js 應(yīng)用

NPM 使用介紹使用 npm 命令安裝模塊本地安裝使用 package.json模塊的操作

回調(diào)函數(shù)阻塞代碼實例非阻塞代碼

事件循環(huán)事件驅(qū)動程序

EventEmitterEventEmitter 類方法實例error 事件繼承 EventEmitter

Buffer(緩沖區(qū))Buffer 與字符編碼創(chuàng)建 Buffer 類寫入緩沖區(qū)從緩沖區(qū)讀取數(shù)據(jù)將 Buffer 轉(zhuǎn)換為 JSON 對象緩沖區(qū)合并緩沖區(qū)比較拷貝緩沖區(qū)緩沖區(qū)裁剪緩沖區(qū)長度

Stream(流)從流中讀取數(shù)據(jù)寫入流管道流鏈?zhǔn)搅?/p>

模塊系統(tǒng)引入模塊

函數(shù)匿名函數(shù)函數(shù)傳遞是如何讓 HTTP 服務(wù)器工作的

路由全局對象__filename__dirnamesetTimeout(cb, ms)clearTimeout(t)setInterval(cb, ms)consoleprocessProcess 屬性方法參考手冊

常用工具util.callbackifyutil.inheritsutil.inspectutil.isArrayutil.isRegExp(object)util.isDate(object)

文件系統(tǒng)異步和同步打開文件獲取文件信息寫入文件讀取文件關(guān)閉文件截取文件刪除文件創(chuàng)建目錄讀取目錄刪除目錄

GET/POST 請求獲取 GET 請求內(nèi)容獲取 POST 請求內(nèi)容

Web 模塊Web 應(yīng)用架構(gòu)使用 Node 創(chuàng)建 Web 服務(wù)器使用 Node 創(chuàng)建 Web 客戶端

Express 框架安裝第一個 Express 框架實例請求和響應(yīng)路由靜態(tài)文件GET 方法POST 方法文件上傳Cookie 管理

RESTful API創(chuàng)建 RESTful獲取用戶列表:添加用戶顯示用戶詳情刪除用戶

多進程exec() 方法

創(chuàng)建第一個應(yīng)用

讓我們先了解下 Node.js 應(yīng)用是由哪幾部分組成的:

require 指令:在 Node.js 中,使用 require 指令來加載和引入模塊,引入的模塊可以是內(nèi)置模塊,也可以是第三方模塊或自定義模塊。 創(chuàng)建服務(wù)器:服務(wù)器可以監(jiān)聽客戶端的請求,類似于 Apache 、Nginx 等 HTTP 服務(wù)器。 接收請求與響應(yīng)請求: 服務(wù)器很容易創(chuàng)建,客戶端可以使用瀏覽器或終端發(fā)送 HTTP 請求,服務(wù)器接收請求后返回響應(yīng)數(shù)據(jù)。

創(chuàng)建 Node.js 應(yīng)用

步驟一、使用 require 指令來加載和引入模塊

const module = require('module-name');

其中,module-name 可以是一個文件路徑(相對或絕對路徑),也可以是一個模塊名稱,如果是一個模塊名稱,Node.js 會自動從 node_modules 目錄中查找該模塊。

我們使用 require 指令來載入 http 模塊,并將實例化的 HTTP 賦值給變量 http,實例如下:

var http = require("http");

步驟二、創(chuàng)建服務(wù)器 接下來我們使用 http.createServer() 方法創(chuàng)建服務(wù)器,并使用 listen 方法綁定 8888 端口。 函數(shù)通過 request, response 參數(shù)來接收和響應(yīng)數(shù)據(jù)。

實例如下,在你項目的根目錄下創(chuàng)建一個叫 server.js 的文件,并寫入以下代碼:

var http = require('http');

http.createServer(function (request, response) {

// 發(fā)送 HTTP 頭部

// HTTP 狀態(tài)值: 200 : OK

// 內(nèi)容類型: text/plain

response.writeHead(200, {'Content-Type': 'text/plain'});

// 發(fā)送響應(yīng)數(shù)據(jù) "Hello World"

response.end('Hello World\n');

}).listen(8888);

// 終端打印如下信息

console.log('Server running at http://127.0.0.1:8888/');

以上代碼我們完成了一個可以工作的 HTTP 服務(wù)器。

使用 node 命令執(zhí)行以上的代碼:

node server.js

接下來,打開瀏覽器訪問 http://127.0.0.1:8888/,你會看到一個寫著 "Hello World"的網(wǎng)頁。 分析Node.js 的 HTTP 服務(wù)器:

第一行請求(require)Node.js 自帶的 http 模塊,并且把它賦值給 http 變量。接下來我們調(diào)用 http 模塊提供的函數(shù): createServer 。這個函數(shù)會返回 一個對象,這個對象有一個叫做 listen 的方法,這個方法有一個數(shù)值參數(shù), 指定這個 HTTP 服務(wù)器監(jiān)聽的端口號。

NPM 使用介紹

NPM是隨同NodeJS一起安裝的包管理工具,能解決NodeJS代碼部署上的很多問題。

可以通過輸入 “npm -v” 來測試是否成功安裝。

使用 npm 命令安裝模塊

以下實例,我們使用 npm 命令安裝常用的 Node.js web框架模塊 express:

npm install express

安裝好之后,express 包就放在了工程目錄下的 node_modules 目錄中,因此在代碼中只需要通過 require(‘express’) 的方式就好,無需指定第三方包路徑。

var express = require('express');

本地安裝

將安裝包放在 ./node_modules 下(運行 npm 命令時所在的目錄),如果沒有 node_modules 目錄,會在當(dāng)前執(zhí)行 npm 命令的目錄下生成 node_modules 目錄??梢酝ㄟ^ require() 來引入本地安裝的包。

使用 package.json

package.json 位于模塊的目錄下,用于定義包的屬性。

模塊的操作

卸載模塊

npm uninstall express

卸載后,你可以到 /node_modules/ 目錄下查看包是否還存在,或者使用以下命令查看:

npm ls

更新模塊

npm update express

搜索模塊

npm search express

回調(diào)函數(shù)

Node.js 異步編程的直接體現(xiàn)就是回調(diào)。

異步編程依托于回調(diào)來實現(xiàn),但不能說使用了回調(diào)后程序就異步化了。

回調(diào)函數(shù)在完成任務(wù)后就會被調(diào)用,Node 使用了大量的回調(diào)函數(shù),Node 所有 API 都支持回調(diào)函數(shù)。

例如,我們可以一邊讀取文件,一邊執(zhí)行其他命令,在文件讀取完成后,我們將文件內(nèi)容作為回調(diào)函數(shù)的參數(shù)返回。這樣在執(zhí)行代碼時就沒有阻塞或等待文件 I/O 操作。這就大大提高了 Node.js 的性能,可以處理大量的并發(fā)請求。

回調(diào)函數(shù)一般作為函數(shù)的最后一個參數(shù)出現(xiàn):

function foo1(name, age, callback) { }

function foo2(value, callback1, callback2) { }

阻塞代碼實例

創(chuàng)建一個文件 input.txt ,內(nèi)容如下:

菜鳥教程官網(wǎng)地址:www.runoob.com

創(chuàng)建 main.js 文件, 代碼如下:

var fs = require("fs");

var data = fs.readFileSync('input.txt');

console.log(data.toString());

console.log("程序執(zhí)行結(jié)束!");

以上代碼執(zhí)行結(jié)果如下:

非阻塞代碼

創(chuàng)建 main.js 文件, 代碼如下:

var fs = require("fs");

fs.readFile('input.txt', function (err, data) {

if (err) return console.error(err);

console.log(data.toString());

});

console.log("程序執(zhí)行結(jié)束!");

以上兩個實例我們了解了阻塞與非阻塞調(diào)用的不同。第一個實例在文件讀取完后才執(zhí)行程序。 第二個實例我們不需要等待文件讀取完,這樣就可以在讀取文件時同時執(zhí)行接下來的代碼,大大提高了程序的性能。

因此,阻塞是按順序執(zhí)行的,而非阻塞是不需要按順序的,所以如果需要處理回調(diào)函數(shù)的參數(shù),我們就需要寫在回調(diào)函數(shù)內(nèi)。

事件循環(huán)

事件驅(qū)動程序

Node.js 使用事件驅(qū)動模型,當(dāng)web server接收到請求,就把它關(guān)閉然后進行處理,然后去服務(wù)下一個web請求。

當(dāng)這個請求完成,它被放回處理隊列,當(dāng)?shù)竭_隊列開頭,這個結(jié)果被返回給用戶。

這個模型非常高效可擴展性非常強,因為 webserver 一直接受請求而不等待任何讀寫操作。

在事件驅(qū)動模型中,會生成一個主循環(huán)來監(jiān)聽事件,當(dāng)檢測到事件時觸發(fā)回調(diào)函數(shù)。

Node.js 有多個內(nèi)置的事件,我們可以通過引入 events 模塊,并通過實例化 EventEmitter 類來綁定和監(jiān)聽事件,如下實例:

創(chuàng)建 main.js 文件,代碼如下所示:

// 引入 events 模塊

var events = require('events');

// 創(chuàng)建 eventEmitter 對象

var eventEmitter = new events.EventEmitter();

// 創(chuàng)建事件處理程序

var connectHandler = function connected() {

console.log('連接成功。');

// 觸發(fā) data_received 事件

eventEmitter.emit('data_received');

}

// 綁定 connection 事件處理程序

eventEmitter.on('connection', connectHandler);

// 使用匿名函數(shù)綁定 data_received 事件

eventEmitter.on('data_received', function(){

console.log('數(shù)據(jù)接收成功。');

});

// 觸發(fā) connection 事件

eventEmitter.emit('connection');

console.log("程序執(zhí)行完畢。");

EventEmitter

Node.js 所有的異步 I/O 操作在完成時都會發(fā)送一個事件到事件隊列。

EventEmitter 類

events 模塊只提供了一個對象: events.EventEmitter。EventEmitter 的核心就是事件觸發(fā)與事件監(jiān)聽器功能的封裝。

你可以通過require(“events”);來訪問該模塊。

// 引入 events 模塊

var events = require('events');

// 創(chuàng)建 eventEmitter 對象

var eventEmitter = new events.EventEmitter();

下面我們用一個簡單的例子說明 EventEmitter 的用法:

//event.js 文件

var EventEmitter = require('events').EventEmitter;

var event = new EventEmitter();

event.on('some_event', function() {

console.log('some_event 事件觸發(fā)');

});

setTimeout(function() {

event.emit('some_event');

}, 1000);

運行這段代碼,1 秒后控制臺輸出了 ‘some_event 事件觸發(fā)’。

其原理是 event 對象注冊了事件 some_event 的一個監(jiān)聽器,然后我們通過 setTimeout 在 1000 毫秒以后向 event 對象發(fā)送事件 some_event,此時會調(diào)用some_event 的監(jiān)聽器。

EventEmitter 的每個事件由一個事件名和若干個參數(shù)組成,事件名是一個字符串,通常表達一定的語義。對于每個事件,EventEmitter 支持 若干個事件監(jiān)聽器。

當(dāng)事件觸發(fā)時,注冊到這個事件的事件監(jiān)聽器被依次調(diào)用,事件參數(shù)作為回調(diào)函數(shù)參數(shù)傳遞。

讓我們以下面的例子解釋這個過程:

//event.js 文件

var events = require('events');

var emitter = new events.EventEmitter();

emitter.on('someEvent', function(arg1, arg2) {

console.log('listener1', arg1, arg2);

});

emitter.on('someEvent', function(arg1, arg2) {

console.log('listener2', arg1, arg2);

});

emitter.emit('someEvent', 'arg1 參數(shù)', 'arg2 參數(shù)');

以上例子中,emitter 為事件 someEvent 注冊了兩個事件監(jiān)聽器,然后觸發(fā)了 someEvent 事件。

運行結(jié)果中可以看到兩個事件監(jiān)聽器回調(diào)函數(shù)被先后調(diào)用。 這就是EventEmitter最簡單的用法。

EventEmitter 提供了多個屬性,如 on 和 emit。on 函數(shù)用于綁定事件函數(shù),emit 屬性用于觸發(fā)一個事件。接下來我們來具體看下 EventEmitter 的屬性介紹。

方法

addListener(event, listener) 為指定事件添加一個監(jiān)聽器到監(jiān)聽器數(shù)組的尾部。on(event, listener) 為指定事件注冊一個監(jiān)聽器,接受一個字符串 event 和一個回調(diào)函數(shù)。

server.on('connection', function (stream) {

console.log('someone connected!');

});

once(event, listener) 為指定事件注冊一個單次監(jiān)聽器,即 監(jiān)聽器最多只會觸發(fā)一次,觸發(fā)后立刻解除該監(jiān)聽器。

server.once('connection', function (stream) {

console.log('Ah, we have our first user!');

});

removeListener(event, listener) 移除指定事件的某個監(jiān)聽器,監(jiān)聽器必須是該事件已經(jīng)注冊過的監(jiān)聽器。

它接受兩個參數(shù),第一個是事件名稱,第二個是回調(diào)函數(shù)名稱。

var callback = function(stream) {

console.log('someone connected!');

};

server.on('connection', callback);

// ...

server.removeListener('connection', callback);

類方法 listenerCount(emitter, event) 返回指定事件的監(jiān)聽器數(shù)量。

events.emitter.listenerCount(eventName) //推薦

實例

以下實例通過 connection(連接)事件演示了 EventEmitter 類的應(yīng)用。

創(chuàng)建 main.js 文件,代碼如下:

var events = require('events');

var eventEmitter = new events.EventEmitter();

// 監(jiān)聽器 #1

var listener1 = function listener1() {

console.log('監(jiān)聽器 listener1 執(zhí)行。');

}

// 監(jiān)聽器 #2

var listener2 = function listener2() {

console.log('監(jiān)聽器 listener2 執(zhí)行。');

}

// 綁定 connection 事件,處理函數(shù)為 listener1

eventEmitter.addListener('connection', listener1);

// 綁定 connection 事件,處理函數(shù)為 listener2

eventEmitter.on('connection', listener2);

var eventListeners = eventEmitter.listenerCount('connection');

console.log(eventListeners + " 個監(jiān)聽器監(jiān)聽連接事件。");

// 處理 connection 事件

eventEmitter.emit('connection');

// 移除監(jiān)綁定的 listener1 函數(shù)

eventEmitter.removeListener('connection', listener1);

console.log("listener1 不再受監(jiān)聽。");

// 觸發(fā)連接事件

eventEmitter.emit('connection');

eventListeners = eventEmitter.listenerCount('connection');

console.log(eventListeners + " 個監(jiān)聽器監(jiān)聽連接事件。");

console.log("程序執(zhí)行完畢。");

error 事件

EventEmitter 定義了一個特殊的事件 error,它包含了錯誤的語義,我們在遇到 異常的時候通常會觸發(fā) error 事件。 我們一般要為會觸發(fā) error 事件的對象設(shè)置監(jiān)聽器,避免遇到錯誤后整個程序崩潰。例如:

var events = require('events');

var emitter = new events.EventEmitter();

emitter.emit('error');

繼承 EventEmitter

大多數(shù)時候我們不會直接使用 EventEmitter,而是在對象中繼承它。包括 fs、net、 http 在內(nèi)的,只要是支持事件響應(yīng)的核心模塊都是 EventEmitter 的子類。

Buffer(緩沖區(qū))

在 Node.js 中,Buffer 類是隨 Node 內(nèi)核一起發(fā)布的核心庫。Buffer 庫為 Node.js 帶來了一種存儲原始數(shù)據(jù)的方法,可以讓 Node.js 處理二進制數(shù)據(jù),每當(dāng)需要在 Node.js 中處理I/O操作中移動的數(shù)據(jù)時,就有可能使用 Buffer 庫。

Buffer 與字符編碼

Buffer 實例一般用于表示編碼字符的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六進制編碼的數(shù)據(jù)。

const buf = Buffer.from('runoob', 'ascii');

// 輸出 72756e6f6f62

console.log(buf.toString('hex'));

// 輸出 cnVub29i

console.log(buf.toString('base64'));

創(chuàng)建 Buffer 類

Buffer 提供了以下 API 來創(chuàng)建 Buffer 類:

// 創(chuàng)建一個長度為 10、且用 0 填充的 Buffer。

const buf1 = Buffer.alloc(10);

// 創(chuàng)建一個長度為 10、且用 0x1 填充的 Buffer。

const buf2 = Buffer.alloc(10, 1);

// 創(chuàng)建一個長度為 10、且未初始化的 Buffer。

// 這個方法比調(diào)用 Buffer.alloc() 更快,

// 但返回的 Buffer 實例可能包含舊數(shù)據(jù),

// 因此需要使用 fill() 或 write() 重寫。

const buf3 = Buffer.allocUnsafe(10);

// 創(chuàng)建一個包含 [0x1, 0x2, 0x3] 的 Buffer。

const buf4 = Buffer.from([1, 2, 3]);

// 創(chuàng)建一個包含 UTF-8 字節(jié) [0x74, 0xc3, 0xa9, 0x73, 0x74] 的 Buffer。

const buf5 = Buffer.from('tést');

// 創(chuàng)建一個包含 Latin-1 字節(jié) [0x74, 0xe9, 0x73, 0x74] 的 Buffer。

const buf6 = Buffer.from('tést', 'latin1');

寫入緩沖區(qū)

語法:

buf.write(string[, offset[, length]][, encoding])

參數(shù):

string - 寫入緩沖區(qū)的字符串。 offset - 緩沖區(qū)開始寫入的索引值,默認為 0 。 length - 寫入的字節(jié)數(shù),默認為 buffer.length encoding - 使用的編碼。默認為 ‘utf8’ 。 根據(jù) encoding 的字符編碼寫入 string 到 buf 中的 offset 位置。 length 參數(shù)是寫入的字節(jié)數(shù)。 返回值 返回實際寫入的大小。 實例

buf = Buffer.alloc(256);

len = buf.write("www.runoob.com");

console.log("寫入字節(jié)數(shù) : "+ len);

從緩沖區(qū)讀取數(shù)據(jù)

語法

buf.toString([encoding[, start[, end]]])

參數(shù)

encoding - 使用的編碼。默認為 ‘utf8’ 。 start - 指定開始讀取的索引位置,默認為 0。 end - 結(jié)束位置,默認為緩沖區(qū)的末尾。

返回值 解碼緩沖區(qū)數(shù)據(jù)并使用指定的編碼返回字符串。

實例

buf = Buffer.alloc(26);

for (var i = 0 ; i < 26 ; i++) {

buf[i] = i + 97;

}

console.log( buf.toString('ascii')); // 輸出: abcdefghijklmnopqrstuvwxyz

console.log( buf.toString('ascii',0,5)); //使用 'ascii' 編碼, 并輸出: abcde

console.log( buf.toString('utf8',0,5)); // 使用 'utf8' 編碼, 并輸出: abcde

console.log( buf.toString(undefined,0,5)); // 使用默認的 'utf8' 編碼, 并輸出: abcde

將 Buffer 轉(zhuǎn)換為 JSON 對象

語法

buf.toJSON()

返回值 返回 JSON 對象。

實例

const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);

const json = JSON.stringify(buf);

// 輸出: {"type":"Buffer","data":[1,2,3,4,5]}

console.log(json);

const copy = JSON.parse(json, (key, value) => {

return value && value.type === 'Buffer' ?

Buffer.from(value.data) :

value;

});

// 輸出:

console.log(copy);

JSON 通常用于與服務(wù)端交換數(shù)據(jù)。 我們可以使用 JSON.parse() 方法將數(shù)據(jù)轉(zhuǎn)換為 JavaScript 對象。

緩沖區(qū)合并

語法

Buffer.concat(list[, totalLength])

參數(shù)

list - 用于合并的 Buffer 對象數(shù)組列表。 totalLength - 指定合并后Buffer對象的總長度。

返回值 返回一個多個成員合并的新 Buffer 對象。

實例

var buffer1 = Buffer.from(('菜鳥教程'));

var buffer2 = Buffer.from(('www.runoob.com'));

var buffer3 = Buffer.concat([buffer1,buffer2]);

console.log("buffer3 內(nèi)容: " + buffer3.toString());

緩沖區(qū)比較

語法

buf.compare(otherBuffer);

參數(shù)

otherBuffer - 與 buf 對象比較的另外一個 Buffer 對象。

返回值 返回一個數(shù)字,表示 buf 在 otherBuffer 之前,之后或相同。

實例

var buffer1 = Buffer.from('ABC');

var buffer2 = Buffer.from('ABCD');

var result = buffer1.compare(buffer2);

if(result < 0) {

console.log(buffer1 + " 在 " + buffer2 + "之前");

}else if(result == 0){

console.log(buffer1 + " 與 " + buffer2 + "相同");

}else {

console.log(buffer1 + " 在 " + buffer2 + "之后");

}

拷貝緩沖區(qū)

語法

buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])

參數(shù)

targetBuffer - 要拷貝的 Buffer 對象。 targetStart - 數(shù)字, 可選, 默認: 0 sourceStart - 數(shù)字, 可選, 默認: 0 sourceEnd - 數(shù)字, 可選, 默認: buffer.length

實例

var buf1 = Buffer.from('abcdefghijkl');

var buf2 = Buffer.from('RUNOOB');

//將 buf2 插入到 buf1 指定位置上

buf2.copy(buf1, 2);

console.log(buf1.toString());

緩沖區(qū)裁剪

語法

buf.slice([start[, end]])

參數(shù)

start - 數(shù)字, 可選, 默認: 0 end - 數(shù)字, 可選, 默認: buffer.length

返回值 返回一個新的緩沖區(qū),它和舊緩沖區(qū)指向同一塊內(nèi)存,但是從索引 start 到 end 的位置剪切。

實例

var buffer1 = Buffer.from('runoob');

// 剪切緩沖區(qū)

var buffer2 = buffer1.slice(0,2);

console.log("buffer2 content: " + buffer2.toString());

緩沖區(qū)長度

語法

buf.length;

返回值 返回 Buffer 對象所占據(jù)的內(nèi)存長度。

實例

var buffer = Buffer.from('www.runoob.com');

// 緩沖區(qū)長度

console.log("buffer length: " + buffer.length);

Stream(流)

Stream 是一個抽象接口,Node 中有很多對象實現(xiàn)了這個接口。

所有的 Stream 對象都是 EventEmitter 的實例。常用的事件有:

data - 當(dāng)有數(shù)據(jù)可讀時觸發(fā)。 end - 沒有更多的數(shù)據(jù)可讀時觸發(fā)。 error - 在接收和寫入過程中發(fā)生錯誤時觸發(fā)。 finish - 所有數(shù)據(jù)已被寫入到底層系統(tǒng)時觸發(fā)。

從流中讀取數(shù)據(jù)

創(chuàng)建 input.txt 文件,內(nèi)容如下:

菜鳥教程官網(wǎng)地址:www.runoob.com

創(chuàng)建 main.js 文件, 代碼如下:

var fs = require("fs");

var data = '';

// 創(chuàng)建可讀流

var readerStream = fs.createReadStream('input.txt');

// 設(shè)置編碼為 utf8。

readerStream.setEncoding('UTF8');

// 處理流事件 --> data, end, and error

readerStream.on('data', function(chunk) {

data += chunk;

});

readerStream.on('end',function(){

console.log(data);

});

readerStream.on('error', function(err){

console.log(err.stack);

});

console.log("程序執(zhí)行完畢");

寫入流

var fs = require("fs");

var data = '菜鳥教程官網(wǎng)地址:www.runoob.com';

// 創(chuàng)建一個可以寫入的流,寫入到文件 output.txt 中

var writerStream = fs.createWriteStream('output.txt');

// 使用 utf8 編碼寫入數(shù)據(jù)

writerStream.write(data,'UTF8');

// 標(biāo)記文件末尾

writerStream.end();

// 處理流事件 --> finish、error

writerStream.on('finish', function() {

console.log("寫入完成。");

});

writerStream.on('error', function(err){

console.log(err.stack);

});

console.log("程序執(zhí)行完畢");

管道流

管道提供了一個輸出流到輸入流的機制。通常我們用于從一個流中獲取數(shù)據(jù)并將數(shù)據(jù)傳遞到另外一個流中。

以下實例我們通過讀取一個文件內(nèi)容并將內(nèi)容寫入到另外一個文件中。

設(shè)置 input.txt 文件內(nèi)容如下:

菜鳥教程官網(wǎng)地址:www.runoob.com

管道流操作實例

創(chuàng)建 main.js 文件, 代碼如下:

var fs = require("fs");

// 創(chuàng)建一個可讀流

var readerStream = fs.createReadStream('input.txt');

// 創(chuàng)建一個可寫流

var writerStream = fs.createWriteStream('output.txt');

// 管道讀寫操作

// 讀取 input.txt 文件內(nèi)容,并將內(nèi)容寫入到 output.txt 文件中

readerStream.pipe(writerStream);

console.log("程序執(zhí)行完畢");

鏈?zhǔn)搅?/p>

鏈?zhǔn)绞峭ㄟ^連接輸出流到另外一個流并創(chuàng)建多個流操作鏈的機制。鏈?zhǔn)搅饕话阌糜诠艿啦僮鳌?/p>

接下來我們就是用管道和鏈?zhǔn)絹韷嚎s和解壓文件。

創(chuàng)建 compress.js 文件, 代碼如下:

var fs = require("fs");

var zlib = require('zlib');

// 壓縮 input.txt 文件為 input.txt.gz

fs.createReadStream('input.txt')

.pipe(zlib.createGzip())

.pipe(fs.createWriteStream('input.txt.gz'));

console.log("文件壓縮完成。");

執(zhí)行完以上操作后,我們可以看到當(dāng)前目錄下生成了 input.txt 的壓縮文件 input.txt.gz。

接下來,讓我們來解壓該文件,創(chuàng)建 decompress.js 文件,代碼如下:

var fs = require("fs");

var zlib = require('zlib');

// 解壓 input.txt.gz 文件為 input.txt

fs.createReadStream('input.txt.gz')

.pipe(zlib.createGunzip())

.pipe(fs.createWriteStream('input.txt'));

console.log("文件解壓完成。");

模塊系統(tǒng)

一個 Node.js 文件就是一個模塊,這個文件可能是JavaScript 代碼、JSON 或者編譯過的C/C++ 擴展。

引入模塊

我們創(chuàng)建一個 main.js 文件并引入 hello 模塊,代碼如下:

var hello = require('./hello');

hello.world();

以上實例中,代碼 require(‘./hello’) 引入了當(dāng)前目錄下的 hello.js 文件(./ 為當(dāng)前目錄,node.js 默認后綴為 js)。

接下來我們就來創(chuàng)建 hello.js 文件,代碼如下:

exports.world = function() {

console.log('Hello World');

}

有時候我們只是想把一個對象封裝到模塊中,格式如下:

//hello.js

function Hello() {

var name;

this.setName = function(thyName) {

name = thyName;

};

this.sayHello = function() {

console.log('Hello ' + name);

};

};

module.exports = Hello;

這樣就可以直接獲得這個對象了:

//main.js

var Hello = require('./hello');

hello = new Hello();

hello.setName('BYVoid');

hello.sayHello();

函數(shù)

在 JavaScript中,一個函數(shù)可以作為另一個函數(shù)的參數(shù)。我們可以先定義一個函數(shù),然后傳遞,也可以在傳遞參數(shù)的地方直接定義函數(shù)。

function say(word) {

console.log(word);

}

function execute(someFunction, value) {

someFunction(value);

}

execute(say, "Hello");

以上代碼中,我們把 say 函數(shù)作為 execute 函數(shù)的第一個變量進行了傳遞。這里傳遞的不是 say 的返回值,而是 say 本身!

這樣一來, say 就變成了execute 中的本地變量 someFunction ,execute 可以通過調(diào)用 someFunction() (帶括號的形式)來使用 say 函數(shù)。

當(dāng)然,因為 say 有一個變量, execute 在調(diào)用 someFunction 時可以傳遞這樣一個變量。

匿名函數(shù)

我們可以把一個函數(shù)作為變量傳遞。但是我們不一定要"先定義,再傳遞"。

我們可以直接在另一個函數(shù)的括號中定義和傳遞這個函數(shù):

function execute(someFunction, value) {

someFunction(value);

}

execute(function(word){ console.log(word) }, "Hello");

我們在 execute 接受第一個參數(shù)的地方直接定義了我們準(zhǔn)備傳遞給 execute 的函數(shù)。

用這種方式,我們甚至不用給這個函數(shù)起名字,這也是為什么它被叫做匿名函數(shù) 。

函數(shù)傳遞是如何讓 HTTP 服務(wù)器工作的

var http = require("http");

http.createServer(function(request, response) {

response.writeHead(200, {"Content-Type": "text/plain"});

response.write("Hello World");

response.end();

}).listen(8888);

現(xiàn)在它看上去應(yīng)該清晰了很多:我們向 createServer 函數(shù)傳遞了一個匿名函數(shù)。

路由

我們需要的所有數(shù)據(jù)都會包含在 request 對象中,該對象作為 onRequest() 回調(diào)函數(shù)的第一個參數(shù)傳遞。

但是為了解析這些數(shù)據(jù),我們需要額外的 Node.JS 模塊,它們分別是 url 和 querystring 模塊。

url.parse(string).query

|

url.parse(string).pathname |

| |

| |

------|-------------------

http://localhost:8888/start?foo=bar&hello=world

--- -----

| |

| |

querystring.parse(queryString)["foo"] |

|

querystring.parse(queryString)["hello"]

現(xiàn)在我們來給 onRequest() 函數(shù)加上一些邏輯,用來找出瀏覽器請求的 URL 路徑:

var http = require("http");

var url = require("url");

function start() {

function onRequest(request, response) {

var pathname = url.parse(request.url).pathname;

console.log("Request for " + pathname + " received.");

response.writeHead(200, {"Content-Type": "text/plain"});

response.write("Hello World");

response.end();

}

http.createServer(onRequest).listen(8888);

console.log("Server has started.");

}

exports.start = start;

現(xiàn)在我們可以來編寫路由了,建立一個名為 router.js 的文件,添加以下內(nèi)容:

function route(pathname) {

console.log("About to route a request for " + pathname);

}

exports.route = route;

如你所見,這段代碼什么也沒干,不過對于現(xiàn)在來說這是應(yīng)該的。在添加更多的邏輯以前,我們先來看看如何把路由和服務(wù)器整合起來。

首先,我們來擴展一下服務(wù)器的 start() 函數(shù),以便將路由函數(shù)作為參數(shù)傳遞過去,server.js 文件代碼如下

var http = require("http");

var url = require("url");

function start(route) {

function onRequest(request, response) {

var pathname = url.parse(request.url).pathname;

console.log("Request for " + pathname + " received.");

route(pathname);

response.writeHead(200, {"Content-Type": "text/plain"});

response.write("Hello World");

response.end();

}

http.createServer(onRequest).listen(8888);

console.log("Server has started.");

}

exports.start = start;

同時,我們會相應(yīng)擴展 index.js,使得路由函數(shù)可以被注入到服務(wù)器中:

var server = require("./server");

var router = require("./router");

server.start(router.route);

如果現(xiàn)在啟動應(yīng)用(node index.js,始終記得這個命令行),隨后請求一個URL,你將會看到應(yīng)用輸出相應(yīng)的信息,這表明我們的HTTP服務(wù)器已經(jīng)在使用路由模塊了,并會將請求的路徑傳遞給路由:

瀏覽器訪問 http://127.0.0.1:8888/,輸出結(jié)果如下:

全局對象

全局對象(Global Object),它及其所有屬性都可以在程序的任何地方訪問。

Node.js 中的全局對象是 global,所有全局變量都是 global 對象的屬性。

在 Node.js 我們可以直接訪問到 global 的屬性,而不需要在應(yīng)用中包含它。

__filename

__filename 表示當(dāng)前正在執(zhí)行的腳本的文件名。它將輸出文件所在位置的絕對路徑。

實例 創(chuàng)建文件 main.js ,代碼如下所示:

// 輸出全局變量 __filename 的值

console.log( __filename );

__dirname

__dirname 表示當(dāng)前執(zhí)行腳本所在的目錄。

實例 創(chuàng)建文件 main.js ,代碼如下所示:

// 輸出全局變量 __dirname 的值

console.log( __dirname );

setTimeout(cb, ms)

setTimeout(cb, ms) 全局函數(shù)在指定的毫秒(ms)數(shù)后執(zhí)行指定函數(shù)(cb)。 實例

function printHello(){

console.log( "Hello, World!");

}

// 兩秒后執(zhí)行以上函數(shù)

setTimeout(printHello, 2000);

兩秒后輸出:

clearTimeout(t)

clearTimeout( t ) 全局函數(shù)用于停止一個之前通過 setTimeout() 創(chuàng)建的定時器。

參數(shù) t 是通過 setTimeout() 函數(shù)創(chuàng)建的定時器。

實例

function printHello(){

console.log( "Hello, World!");

}

// 兩秒后執(zhí)行以上函數(shù)

var t = setTimeout(printHello, 2000);

// 清除定時器

clearTimeout(t);

setInterval(cb, ms)

setInterval(cb, ms) 全局函數(shù)在指定的毫秒(ms)數(shù)后執(zhí)行指定函數(shù)(cb)。

可以使用 clearInterval(t) 函數(shù)來清除定時器。

setInterval() 方法會不停地調(diào)用函數(shù),直到 clearInterval() 被調(diào)用或窗口被關(guān)閉。

實例

function printHello(){

console.log( "Hello, World!");

}

// 兩秒后執(zhí)行以上函數(shù)

setInterval(printHello, 2000);

以上程序每隔兩秒就會輸出一次"Hello, World!",且會永久執(zhí)行下去,直到你按下 ctrl + c 按鈕。

console

console 用于提供控制臺標(biāo)準(zhǔn)輸出。

console.log([data][, …]) 向標(biāo)準(zhǔn)輸出流打印字符并以換行符結(jié)束。console.info([data][, …]) 這個命令與console.log差別并不大console.time(label) 輸出時間,表示計時開始。console.timeEnd(label) 結(jié)束時間,表示計時結(jié)束。

實例

console.info("程序開始執(zhí)行:");

var counter = 10;

console.log("計數(shù): %d", counter);

console.time("獲取數(shù)據(jù)");

//

// 執(zhí)行一些代碼

//

console.timeEnd('獲取數(shù)據(jù)');

console.info("程序執(zhí)行完畢。")

process

process 是一個全局變量,即 global 對象的屬性。

它用于描述當(dāng)前Node.js 進程狀態(tài)的對象,提供了一個與操作系統(tǒng)的簡單接口。

實例 Process 對象的常用的成員方法:exit 當(dāng)進程準(zhǔn)備退出時觸發(fā)。

process.on('exit', function(code) {

// 以下代碼永遠不會執(zhí)行

setTimeout(function() {

console.log("該代碼不會執(zhí)行");

}, 0);

console.log('退出碼為:', code);

});

console.log("程序執(zhí)行結(jié)束");

Process 屬性

stdout 標(biāo)準(zhǔn)輸出流。argv argv 屬性返回一個數(shù)組,由命令行執(zhí)行腳本時的各個參數(shù)組成。 它的第一個成員總是node,第二個成員是腳本文件名,其余成員是腳本文件的參數(shù)。execPath 返回執(zhí)行當(dāng)前腳本的 Node 二進制文件的絕對路徑。platform 運行程序所在的平臺系統(tǒng) ‘darwin’, ‘freebsd’, ‘linux’, ‘sunos’ 或 ‘win32’

// 輸出到終端

process.stdout.write("Hello World!" + "\n");

// 通過參數(shù)讀取

process.argv.forEach(function(val, index, array) {

console.log(index + ': ' + val);

});

// 獲取執(zhí)行路徑

console.log(process.execPath);

// 平臺信息

console.log(process.platform);

方法參考手冊

// 輸出當(dāng)前目錄

console.log('當(dāng)前目錄: ' + process.cwd());

// 輸出當(dāng)前版本

console.log('當(dāng)前版本: ' + process.version);

// 輸出內(nèi)存使用情況

console.log(process.memoryUsage());

常用工具

util 是一個Node.js 核心模塊,提供常用函數(shù)的集合。

使用方法如下:

const util = require('util');

util.callbackify

util.callbackify(original) 將 async 異步函數(shù)(或者一個返回值為 Promise 的函數(shù))轉(zhuǎn)換成遵循異常優(yōu)先的回調(diào)風(fēng)格的函數(shù)。

const util = require('util');

async function fn() {

return 'hello world';

}

const callbackFunction = util.callbackify(fn);

callbackFunction((err, ret) => {

if (err) throw err;

console.log(ret);

});

util.inherits

util.inherits(constructor, superConstructor) 是一個實現(xiàn)對象間原型繼承的函數(shù)。

var util = require('util');

function Base() {

this.name = 'base';

this.base = 1991;

this.sayHello = function() {

console.log('Hello ' + this.name);

};

}

Base.prototype.showName = function() {

console.log(this.name);

};

function Sub() {

this.name = 'sub';

}

util.inherits(Sub, Base);

var objBase = new Base();

objBase.showName();

objBase.sayHello();

console.log(objBase);

var objSub = new Sub();

objSub.showName();

//objSub.sayHello();

console.log(objSub);

我們定義了一個基礎(chǔ)對象 Base 和一個繼承自 Base 的 Sub。 Base 有三個在構(gòu)造函數(shù)內(nèi)定義的屬性和一個原型中定義的函數(shù),通過util.inherits 實現(xiàn)繼承。運行結(jié)果如下:

注意:Sub 僅僅繼承了Base 在原型中定義的函數(shù),而構(gòu)造函數(shù)內(nèi)部創(chuàng)造的 base 屬性和 sayHello 函數(shù)都沒有被 Sub 繼承。

如果我們?nèi)サ?objSub.sayHello(); 這行的注釋,將會看到:

util.inspect

util.inspect(object,[showHidden],[depth],[colors]) 是一個將任意對象轉(zhuǎn)換 為字符串的方法。

showHidden 是一個可選參數(shù),如果值為 true,將會輸出更多隱藏信息。

var util = require('util');

function Person() {

this.name = 'byvoid';

this.toString = function() {

return this.name;

};

}

var obj = new Person();

console.log(util.inspect(obj));

console.log(util.inspect(obj, true));

util.isArray

如果給定的參數(shù) “object” 是一個數(shù)組返回 true,否則返回 false。

var util = require('util');

util.isArray([])

// true

util.isArray(new Array)

// true

util.isArray({})

// false

util.isRegExp(object)

如果給定的參數(shù) “object” 是一個正則表達式返回true,否則返回false。

var util = require('util');

util.isRegExp(/some regexp/)

// true

util.isRegExp(new RegExp('another regexp'))

// true

util.isRegExp({})

// false

util.isDate(object)

如果給定的參數(shù) “object” 是一個日期返回true,否則返回false。

var util = require('util');

util.isDate(new Date())

// true

util.isDate(Date())

// false (without 'new' returns a String)

util.isDate({})

// false

文件系統(tǒng)

Node 導(dǎo)入文件系統(tǒng)模塊(fs)語法如下所示:

var fs = require("fs")

異步和同步

異步的方法函數(shù)最后一個參數(shù)為回調(diào)函數(shù),回調(diào)函數(shù)的第一個參數(shù)包含了錯誤信息(error)。

建議大家使用異步方法,比起同步,異步方法性能更高,速度更快,而且沒有阻塞。

實例 創(chuàng)建 input.txt 文件,內(nèi)容如下:

菜鳥教程官網(wǎng)地址:www.runoob.com

文件讀取實例

創(chuàng)建 file.js 文件, 代碼如下:

var fs = require("fs");

// 異步讀取

fs.readFile('input.txt', function (err, data) {

if (err) {

return console.error(err);

}

console.log("異步讀取: " + data.toString());

});

// 同步讀取

var data = fs.readFileSync('input.txt');

console.log("同步讀取: " + data.toString());

console.log("程序執(zhí)行完畢。");

打開文件

語法

fs.open(path, flags[, mode], callback)

參數(shù)

path - 文件的路徑。 flags - 文件打開的行為。flags 參數(shù)可以是以下值:

r 以讀取模式打開文件。w 以寫入模式打開文件。r+/w+ 以讀寫模式打開文件。 mode - 設(shè)置文件模式(權(quán)限),文件創(chuàng)建默認權(quán)限為 0666(可讀,可寫)。 callback - 回調(diào)函數(shù),帶有兩個參數(shù)如:callback(err, fd)。

實例 創(chuàng)建 file.js 文件,并打開 input.txt 文件進行讀寫,代碼如下所示:

var fs = require("fs");

// 異步打開文件

console.log("準(zhǔn)備打開文件!");

fs.open('input.txt', 'r+', function(err, fd) {

if (err) {

return console.error(err);

}

console.log("文件打開成功!");

});

獲取文件信息

語法 以下為通過異步模式獲取文件信息的語法格式:

fs.stat(path, callback)

參數(shù)

path - 文件路徑。callback - 回調(diào)函數(shù),帶有兩個參數(shù)如:(err, stats), stats 是 fs.Stats 對象。

fs.stat(path)執(zhí)行后,會將 stats 類的實例返回給其回調(diào)函數(shù)??梢酝ㄟ^ stats 類中的提供方法判斷文件的相關(guān)屬性。例如判斷是否為文件:

var fs = require('fs');

fs.stat('/Users/liuht/code/itbilu/demo/fs.js', function (err, stats) {

console.log(stats.isFile()); //true

})

實例

var fs = require("fs");

console.log("準(zhǔn)備打開文件!");

fs.stat('input.txt', function (err, stats) {

if (err) {

return console.error(err);

}

console.log(stats);

console.log("讀取文件信息成功!");

// 檢測文件類型

console.log("是否為文件(isFile) ? " + stats.isFile());

console.log("是否為目錄(isDirectory) ? " + stats.isDirectory());

});

寫入文件

語法

fs.writeFile(file, data[, options], callback)

writeFile 直接打開文件默認是 w 模式,所以如果文件存在,該方法寫入的內(nèi)容會覆蓋舊的文件內(nèi)容。 參數(shù)

file - 文件名或文件描述符。 data - 要寫入文件的數(shù)據(jù),可以是 String(字符串) 或 Buffer(緩沖) 對象。 options - 該參數(shù)是一個對象,包含 {encoding, mode, flag}。默認編碼為 utf8, 模式為 0666 , flag 為 ‘w’ callback - 回調(diào)函數(shù),回調(diào)函數(shù)只包含錯誤信息參數(shù)(err),在寫入失敗時返回。

實例 接下來我們創(chuàng)建 file.js 文件,代碼如下所示:

var fs = require("fs");

console.log("準(zhǔn)備寫入文件");

fs.writeFile('input.txt', '我是通 過fs.writeFile 寫入文件的內(nèi)容', function(err) {

if (err) {

return console.error(err);

}

console.log("數(shù)據(jù)寫入成功!");

console.log("--------我是分割線-------------")

console.log("讀取寫入的數(shù)據(jù)!");

fs.readFile('input.txt', function (err, data) {

if (err) {

return console.error(err);

}

console.log("異步讀取文件數(shù)據(jù): " + data.toString());

});

});

讀取文件

語法 以下為異步模式下讀取文件的語法格式:

fs.read(fd, buffer, offset, length, position, callback)

參數(shù)

fd - 通過 fs.open() 方法返回的文件描述符。 buffer - 數(shù)據(jù)寫入的緩沖區(qū)。 offset - 緩沖區(qū)寫入的寫入偏移量。 length - 要從文件中讀取的字節(jié)數(shù)。 position - 文件讀取的起始位置,如果 position 的值為 null,則會從當(dāng)前文件指針的位置讀取。 callback - 回調(diào)函數(shù),有三個參數(shù)err, bytesRead, buffer,err 為錯誤信息, bytesRead 表示讀取的字節(jié)數(shù),buffer 為緩沖區(qū)對象。

實例 input.txt 文件內(nèi)容為:

菜鳥教程官網(wǎng)地址:www.runoob.com

file.js

var fs = require("fs");

var buf = new Buffer.alloc(1024);

console.log("準(zhǔn)備打開已存在的文件!");

fs.open('input.txt', 'r+', function(err, fd) {

if (err) {

return console.error(err);

}

console.log("文件打開成功!");

console.log("準(zhǔn)備讀取文件:");

fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){

if (err){

console.log(err);

}

console.log(bytes + " 字節(jié)被讀取");

// 僅輸出讀取的字節(jié)

if(bytes > 0){

console.log(buf.slice(0, bytes).toString());

}

});

});

關(guān)閉文件

語法

fs.close(fd, callback)

參數(shù)

fd - 通過 fs.open() 方法返回的文件描述符。 callback - 回調(diào)函數(shù),沒有參數(shù)。

實例 file.js

var fs = require("fs");

var buf = new Buffer.alloc(1024);

console.log("準(zhǔn)備打開文件!");

fs.open('input.txt', 'r+', function(err, fd) {

if (err) {

return console.error(err);

}

console.log("文件打開成功!");

console.log("準(zhǔn)備讀取文件!");

fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){

if (err){

console.log(err);

}

// 僅輸出讀取的字節(jié)

if(bytes > 0){

console.log(buf.slice(0, bytes).toString());

}

// 關(guān)閉文件

fs.close(fd, function(err){

if (err){

console.log(err);

}

console.log("文件關(guān)閉成功");

});

});

});

截取文件

語法

fs.ftruncate(fd, len, callback)

參數(shù)

fd - 通過 fs.open() 方法返回的文件描述符。 len - 文件內(nèi)容截取的長度。 callback - 回調(diào)函數(shù),沒有參數(shù)。

實例 input.txt 文件內(nèi)容為:

site:www.runoob.com

file.js

var fs = require("fs");

var buf = new Buffer.alloc(1024);

console.log("準(zhǔn)備打開文件!");

fs.open('input.txt', 'r+', function(err, fd) {

if (err) {

return console.error(err);

}

console.log("文件打開成功!");

console.log("截取10字節(jié)內(nèi)的文件內(nèi)容,超出部分將被去除。");

// 截取文件

fs.ftruncate(fd, 10, function(err){

if (err){

console.log(err);

}

console.log("文件截取成功。");

console.log("讀取相同的文件");

fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){

if (err){

console.log(err);

}

// 僅輸出讀取的字節(jié)

if(bytes > 0){

console.log(buf.slice(0, bytes).toString());

}

// 關(guān)閉文件

fs.close(fd, function(err){

if (err){

console.log(err);

}

console.log("文件關(guān)閉成功!");

});

});

});

});

刪除文件

語法

fs.unlink(path, callback)

參數(shù)

path - 文件路徑。 callback - 回調(diào)函數(shù),沒有參數(shù)。

實例 file.js

var fs = require("fs");

console.log("準(zhǔn)備刪除文件!");

fs.unlink('input.txt', function(err) {

if (err) {

return console.error(err);

}

console.log("文件刪除成功!");

});

創(chuàng)建目錄

語法

fs.mkdir(path[, options], callback)

參數(shù)

path - 文件路徑。 options 參數(shù)可以是:

recursive - 是否以遞歸的方式創(chuàng)建目錄,默認為 false。mode - 設(shè)置目錄權(quán)限,默認為 0777。 callback - 回調(diào)函數(shù),沒有參數(shù)。

實例 file.js

var fs = require("fs");

// tmp 目錄必須存在

console.log("創(chuàng)建目錄 /tmp/test/");

fs.mkdir("./tmp/test/",function(err){

if (err) {

return console.error(err);

}

console.log("目錄創(chuàng)建成功。");

});

讀取目錄

語法

fs.readdir(path, callback)

參數(shù)

path - 文件路徑。callback - 回調(diào)函數(shù),回調(diào)函數(shù)帶有兩個參數(shù)err, files,err 為錯誤信息,files 為 目錄下的文件數(shù)組列表。

實例 file.js

var fs = require("fs");

console.log("查看 /tmp 目錄");

fs.readdir("/tmp/",function(err, files){

if (err) {

return console.error(err);

}

files.forEach( function (file){

console.log( file );

});

});

刪除目錄

語法

fs.rmdir(path, callback)

參數(shù)

path - 文件路徑。callback - 回調(diào)函數(shù),沒有參數(shù)。

實例 file.js

var fs = require("fs");

// 執(zhí)行前創(chuàng)建一個空的 /tmp/test 目錄

console.log("準(zhǔn)備刪除目錄 /tmp/test");

fs.rmdir("/tmp/test",function(err){

if (err) {

return console.error(err);

}

console.log("讀取 /tmp 目錄");

fs.readdir("/tmp/",function(err, files){

if (err) {

return console.error(err);

}

files.forEach( function (file){

console.log( file );

});

});

});

GET/POST 請求

在很多場景中,我們的服務(wù)器都需要跟用戶的瀏覽器打交道,如表單提交。

表單提交到服務(wù)器一般都使用 GET/POST 請求。

獲取 GET 請求內(nèi)容

由于GET請求直接被嵌入在路徑中,URL是完整的請求路徑,包括了?后面的部分,因此你可以手動解析后面的內(nèi)容作為GET請求的參數(shù)。

node.js 中 url 模塊中的 parse 函數(shù)提供了這個功能。

var http = require('http');

var url = require('url');

var util = require('util');

http.createServer(function(req, res){

res.writeHead(200, {'Content-Type': 'text/plain'});

// 解析 url 參數(shù)

var params = url.parse(req.url, true).query;

res.write("網(wǎng)站名:" + params.name);

res.write("\n");

res.write("網(wǎng)站 URL:" + params.url);

res.end();

}).listen(3000);

獲取 POST 請求內(nèi)容

POST 請求的內(nèi)容全部的都在請求體中。

node.js 默認是不會解析請求體的,當(dāng)你需要的時候,需要手動來做。

var http = require('http');

var querystring = require('querystring');

var util = require('util');

http.createServer(function(req, res){

// 定義了一個post變量,用于暫存請求體的信息

var post = '';

// 通過req的data事件監(jiān)聽函數(shù),每當(dāng)接受到請求體的數(shù)據(jù),就累加到post變量中

req.on('data', function(chunk){

post += chunk;

});

// 在end事件觸發(fā)后,通過querystring.parse將post解析為真正的POST請求格式,然后向客戶端返回。

req.on('end', function(){

post = querystring.parse(post);

res.end(util.inspect(post));

});

}).listen(3000);

Web 模塊

目前最主流的三個Web服務(wù)器是Apache、Nginx、IIS。

Web 應(yīng)用架構(gòu)

Client - 客戶端,一般指瀏覽器,瀏覽器可以通過 HTTP 協(xié)議向服務(wù)器請求數(shù)據(jù)。 Server - 服務(wù)端,一般指 Web 服務(wù)器,可以接收客戶端請求,并向客戶端發(fā)送響應(yīng)數(shù)據(jù)。 Business - 業(yè)務(wù)層, 通過 Web 服務(wù)器處理應(yīng)用程序,如與數(shù)據(jù)庫交互,邏輯運算,調(diào)用外部程序等。 Data - 數(shù)據(jù)層,一般由數(shù)據(jù)庫組成。

使用 Node 創(chuàng)建 Web 服務(wù)器

Node.js 提供了 http 模塊,http 模塊主要用于搭建 HTTP 服務(wù)端和客戶端。

以下是演示一個最基本的 HTTP 服務(wù)器架構(gòu)(使用 8080 端口),創(chuàng)建server.js文件,代碼如下所示:

var http = require('http');

var fs = require('fs');

var url = require('url');

// 創(chuàng)建服務(wù)器

http.createServer( function (request, response) {

// 解析請求,包括文件名

var pathname = url.parse(request.url).pathname;

// 輸出請求的文件名

console.log("Request for " + pathname + " received.");

// 從文件系統(tǒng)中讀取請求的文件內(nèi)容

fs.readFile(pathname.substr(1), function (err, data) {

if (err) {

console.log(err);

// HTTP 狀態(tài)碼: 404 : NOT FOUND

// Content Type: text/html

response.writeHead(404, {'Content-Type': 'text/html'});

}else{

// HTTP 狀態(tài)碼: 200 : OK

// Content Type: text/html

response.writeHead(200, {'Content-Type': 'text/html'});

// 響應(yīng)文件內(nèi)容

response.write(data.toString());

}

// 發(fā)送響應(yīng)數(shù)據(jù)

response.end();

});

}).listen(8080);

// 控制臺會輸出以下信息

console.log('Server running at http://127.0.0.1:8080/');

執(zhí)行 server.js 程序: 打開地址:

使用 Node 創(chuàng)建 Web 客戶端

client.js

var http = require('http');

// 用于請求的選項

var options = {

host: 'localhost',

port: '8080',

path: '/index.html'

};

// 處理響應(yīng)的回調(diào)函數(shù)

var callback = function(response){

// 不斷更新數(shù)據(jù)

var body = '';

response.on('data', function(data) {

body += data;

});

response.on('end', function() {

// 數(shù)據(jù)接收完成

console.log(body);

});

}

// 向服務(wù)端發(fā)送請求

var req = http.request(options, callback);

req.end();

在 server.js 啟動的情況下,ctrl + shift + ` 新開一個終端,執(zhí)行 client.js 文件: 客戶端請求信息,執(zhí)行 server.js 的控制臺輸出:

Express 框架

使用 Express 可以快速地搭建一個完整功能的網(wǎng)站。

安裝

cnpm install express

cnpm install body-parser

cnpm install cookie-parser

cnpm install multer

以下幾個重要的模塊是需要與 express 框架一起安裝的:

body-parser - 用于處理 JSON, Raw, Text 和 URL 編碼的數(shù)據(jù)。 cookie-parser - 這就是一個解析Cookie的工具。通過req.cookies可以取到傳過來的cookie,并把它們轉(zhuǎn)成對象。 multer - 用于處理 enctype=“multipart/form-data”(設(shè)置表單的MIME編碼)的表單數(shù)據(jù)。

第一個 Express 框架實例

以下實例中我們引入了 express 模塊,并在客戶端發(fā)起請求后,響應(yīng) “Hello World” 字符串。

創(chuàng)建 express_demo.js 文件,代碼如下所示:

var express = require('express');

var app = express();

app.get('/', function (req, res) {

res.send('Hello World');

})

var server = app.listen(8081, '127.0.0.1',function () {

var host = server.address().address

var port = server.address().port

console.log("應(yīng)用實例,訪問地址為 http://%s:%s", host, port)

})

請求和響應(yīng)

Express 應(yīng)用使用回調(diào)函數(shù)的參數(shù): request 和 response 對象來處理請求和響應(yīng)的數(shù)據(jù)。

app.get('/', function (req, res) {

// --

})

Request 對象 - request 對象表示 HTTP 請求,包含了請求查詢字符串,參數(shù),內(nèi)容,HTTP 頭部等屬性。Response 對象 - response 對象表示 HTTP 響應(yīng),即在接收到請求時向客戶端發(fā)送的 HTTP 響應(yīng)數(shù)據(jù)。

路由

路由決定了由誰(指定腳本)去響應(yīng)客戶端請求。

在HTTP請求中,我們可以通過路由提取出請求的URL以及GET/POST參數(shù)。

express_demo2.js

var express = require('express');

var app = express();

// 主頁輸出 "Hello World"

app.get('/', function (req, res) {

console.log("主頁 GET 請求");

res.send('Hello GET');

})

// POST 請求

app.post('/', function (req, res) {

console.log("主頁 POST 請求");

res.send('Hello POST');

})

// /del_user 頁面響應(yīng)

app.get('/del_user', function (req, res) {

console.log("/del_user 響應(yīng) DELETE 請求");

res.send('刪除頁面');

})

// /list_user 頁面 GET 請求

app.get('/list_user', function (req, res) {

console.log("/list_user GET 請求");

res.send('用戶列表頁面');

})

// 對頁面 abcd, abxcd, ab123cd, 等響應(yīng) GET 請求

app.get('/ab*cd', function(req, res) {

console.log("/ab*cd GET 請求");

res.send('正則匹配');

})

var server = app.listen(8081,'127.0.0.1',function () {

var host = server.address().address

var port = server.address().port

console.log("應(yīng)用實例,訪問地址為 http://%s:%s", host, port)

})

靜態(tài)文件

你可以使用express.static中間件來設(shè)置靜態(tài)文件路徑。例如,如果你將圖片, CSS, JavaScript 文件放在 public 目錄下,你可以這么寫:

app.use('/public', express.static('public'));

創(chuàng)建文件夾public/images,放入圖片logo.png express_demo3.js

var express = require('express');

var app = express();

app.use('/public', express.static('public'));

app.get('/', function (req, res) {

res.send('Hello World');

})

var server = app.listen(8081, function () {

var host = server.address().address

var port = server.address().port

console.log("應(yīng)用實例,訪問地址為 http://%s:%s", host, port)

})

訪問網(wǎng)頁:http://127.0.0.1:8081/public/images/logo.png

得到logo.png:

GET 方法

在表單中通過 GET 方法提交兩個參數(shù),我們可以使用 server.js 文件內(nèi)的 process_get 路由器來處理輸入:

index.html 文件代碼:

First Name:

Last Name:

server.js 文件代碼:

var express = require('express');

var app = express();

app.use('/public', express.static('public'));

app.get('/index.html', function (req, res) {

res.sendFile( __dirname + "/" + "index.html" );

})

app.get('/process_get', function (req, res) {

// 輸出 JSON 格式

var response = {

"first_name":req.query.first_name,

"last_name":req.query.last_name

};

console.log(response);

res.end(JSON.stringify(response));

})

var server = app.listen(8081,'127.0.0.1',function () {

var host = server.address().address

var port = server.address().port

console.log("應(yīng)用實例,訪問地址為 http://%s:%s", host, port)

})

POST 方法

在表單中通過 POST 方法提交兩個參數(shù),我們可以使用 server.js 文件內(nèi)的 process_post 路由器來處理輸入:

index.html 文件代碼:

First Name:

Last Name:

server.js 文件代碼:

var express = require('express');

var app = express();

var bodyParser = require('body-parser');

// 創(chuàng)建 application/x-www-form-urlencoded 編碼解析

var urlencodedParser = bodyParser.urlencoded({ extended: false })

app.use('/public', express.static('public'));

app.get('/index.html', function (req, res) {

res.sendFile( __dirname + "/" + "index.html" );

})

app.post('/process_post', urlencodedParser, function (req, res) {

// 輸出 JSON 格式

var response = {

"first_name":req.body.first_name,

"last_name":req.body.last_name

};

console.log(response);

res.end(JSON.stringify(response));

})

var server = app.listen(8081,'127.0.0.1',function () {

var host = server.address().address

var port = server.address().port

console.log("應(yīng)用實例,訪問地址為 http://%s:%s", host, port)

})

文件上傳

創(chuàng)建一個用于上傳文件的表單,使用 POST 方法,表單 enctype 屬性設(shè)置為 multipart/form-data。

index.html 文件代碼:

文件上傳表單

文件上傳:

選擇一個文件上傳:


server.js 文件代碼:

var express = require('express');

var app = express();

var fs = require("fs");

var bodyParser = require('body-parser');

var multer = require('multer');

app.use('/public', express.static('public'));

app.use(bodyParser.urlencoded({ extended: false }));

app.use(multer({ dest: '/tmp/'}).array('image'));

app.get('/index.html', function (req, res) {

res.sendFile( __dirname + "/" + "index.html" );

})

app.post('/file_upload', function (req, res) {

console.log(req.files[0]); // 上傳的文件信息

var des_file = __dirname + "/" + req.files[0].originalname;

fs.readFile( req.files[0].path, function (err, data) {

fs.writeFile(des_file, data, function (err) {

if( err ){

console.log( err );

}else{

response = {

message:'File uploaded successfully',

filename:req.files[0].originalname

};

}

console.log( response );

res.end( JSON.stringify( response ) );

});

});

})

var server = app.listen(8081,'127.0.0.1',function () {

var host = server.address().address

var port = server.address().port

console.log("應(yīng)用實例,訪問地址為 http://%s:%s", host, port)

})

Cookie 管理

使用中間件向 Node.js 服務(wù)器發(fā)送 cookie 信息,以下代碼輸出了客戶端發(fā)送的 cookie 信息: express_cookie.js 文件代碼:

// express_cookie.js 文件

var express = require('express')

var cookieParser = require('cookie-parser')

var util = require('util');

var app = express()

app.use(cookieParser())

app.get('/', function(req, res) {

console.log("Cookies: " + util.inspect(req.cookies));

})

app.listen(8081)

訪問 http://127.0.0.1:8081,并查看終端信息:

RESTful API

REST即表述性狀態(tài)傳遞(英文:Representational State Transfer)。

REST 通常使用 JSON 數(shù)據(jù)格式。

以下為 REST 基本架構(gòu)的四個方法:

GET - 用于獲取數(shù)據(jù)。 PUT - 用于更新或添加數(shù)據(jù)。 DELETE - 用于刪除數(shù)據(jù)。 POST - 用于添加數(shù)據(jù)。

創(chuàng)建 RESTful

首先,創(chuàng)建一個 json 數(shù)據(jù)資源文件 users.json:

{

"user1" : {

"name" : "mahesh",

"password" : "password1",

"profession" : "teacher",

"id": 1

},

"user2" : {

"name" : "suresh",

"password" : "password2",

"profession" : "librarian",

"id": 2

},

"user3" : {

"name" : "ramesh",

"password" : "password3",

"profession" : "clerk",

"id": 3

}

}

獲取用戶列表:

以下代碼,我們創(chuàng)建了 RESTful API listUsers,用于讀取用戶的信息列表, server.js 文件代碼如下所示:

var express = require('express');

var app = express();

var fs = require("fs");

app.get('/listUsers', function (req, res) {

fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {

console.log( data );

res.end( data );

});

})

var server = app.listen(8081,'127.0.0.1',function () {

var host = server.address().address

var port = server.address().port

console.log("應(yīng)用實例,訪問地址為 http://%s:%s", host, port)

})

在瀏覽器中訪問 http://127.0.0.1:8081/listUsers,結(jié)果如下所示:

添加用戶

以下代碼,我們創(chuàng)建了 RESTful API addUser, 用于添加新的用戶數(shù)據(jù),server.js 文件代碼如下所示:

var express = require('express');

var app = express();

var fs = require("fs");

//添加的新用戶數(shù)據(jù)

var user = {

"user4" : {

"name" : "mohit",

"password" : "password4",

"profession" : "teacher",

"id": 4

}

}

app.get('/addUser', function (req, res) {

// 讀取已存在的數(shù)據(jù)

fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {

data = JSON.parse( data );

data["user4"] = user["user4"];

console.log( data );

res.end( JSON.stringify(data));

});

})

var server = app.listen(8081,'127.0.0.1',function () {

var host = server.address().address

var port = server.address().port

console.log("應(yīng)用實例,訪問地址為 http://%s:%s", host, port)

})

顯示用戶詳情

我們創(chuàng)建了 RESTful API :id(用戶id), 用于讀取指定用戶的詳細信息,server.js 文件代碼如下所示:

var express = require('express');

var app = express();

var fs = require("fs");

app.get('/:id', function (req, res) {

// 首先我們讀取已存在的用戶

fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {

data = JSON.parse( data );

var user = data["user" + req.params.id]

console.log( user );

res.end( JSON.stringify(user));

});

})

var server = app.listen(8081,'127.0.0.1',function () {

var host = server.address().address

var port = server.address().port

console.log("應(yīng)用實例,訪問地址為 http://%s:%s", host, port)

})

刪除用戶

我們創(chuàng)建了 RESTful API deleteUser, 用于刪除指定用戶的詳細信息,以下實例中,用戶 id 為 2,server.js 文件代碼如下所示:

var express = require('express');

var app = express();

var fs = require("fs");

var id = 2;

app.get('/deleteUser', function (req, res) {

// First read existing users.

fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {

data = JSON.parse( data );

delete data["user" + id];

console.log( data );

res.end( JSON.stringify(data));

});

})

var server = app.listen(8081,'127.0.0.1',function () {

var host = server.address().address

var port = server.address().port

console.log("應(yīng)用實例,訪問地址為 http://%s:%s", host, port)

})

多進程

Node 提供了 child_process 模塊來創(chuàng)建子進程,方法有:

exec() 方法

讓我們創(chuàng)建兩個 js 文件 support.js 和 master.js。

support.js 文件代碼:

console.log("進程 " + process.argv[2] + " 執(zhí)行。" );

master.js 文件代碼:

const fs = require('fs');

const child_process = require('child_process');

for(var i=0; i<3; i++) {

var workerProcess = child_process.exec('node support.js '+i, function (error, stdout, stderr) {

if (error) {

console.log(error.stack);

console.log('Error code: '+error.code);

console.log('Signal received: '+error.signal);

}

console.log('stdout: ' + stdout);

console.log('stderr: ' + stderr);

});

workerProcess.on('exit', function (code) {

console.log('子進程已退出,退出碼 '+code);

});

}

柚子快報激活碼778899分享:Node.js---菜鳥教程

http://yzkb.51969.com/

好文鏈接

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/15795193.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄