一、Node.js 創(chuàng)建服務(wù)端應(yīng)用
// 使用require指令加載模塊
var http = require('http');
// 使用http.createServer()方法創(chuàng)建服務(wù)器
http.createServer(function (request, response) {
// 通過(guò)request、response參數(shù)來(lái)接口和響應(yīng)數(shù)據(jù)
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World\n');
}).listen(8888);
console.log('Server running at http://127.0.0.1:8888/');
二、npm 使用介紹
NPM是隨同NodeJS一起安裝的包管理工具,能解決NodeJS代碼部署上的很多問(wèn)題,常見(jiàn)的使用場(chǎng)景有以下幾種:
允許用戶從NPM服務(wù)器下載別人編寫的第三方包到本地使用。
允許用戶從NPM服務(wù)器下載并安裝別人編寫的命令行程序到本地使用。
允許用戶將自己編寫的包或命令行程序上傳到NPM服務(wù)器供別人使用。
npm可以分為全局安裝和本地安裝
# 本地安裝
# 將安裝包放在 ./node_modules 下(運(yùn)行 npm 命令時(shí)所在的目錄),
# 如果沒(méi)有 node_modules 目錄,會(huì)在當(dāng)前執(zhí)行 npm 命令的目錄下生成 node_modules 目錄。
# 可以通過(guò) require() 來(lái)引入本地安裝的包。
npm install express
# 全局安裝
# 將安裝包放在 /usr/local 下或者你 node 的安裝目錄。
# 可以直接在命令行里使用。
npm install express -g
三、Node.js 回調(diào)函數(shù)
Node所有API都支持回調(diào)函數(shù),回調(diào)函數(shù)一般作為API的最后一個(gè)參數(shù)出現(xiàn)
阻塞代碼實(shí)例
var fs = require("fs"); // 獲取文件操作對(duì)象
var data = fs.readFileSync('input.txt'); //從input.txt文件中讀取內(nèi)容“菜鳥教程官網(wǎng)地址:www.runoob.com”
console.log(data.toString());
console.log("程序執(zhí)行結(jié)束");
/*
菜鳥教程官網(wǎng)地址:www.runoob.com
程序執(zhí)行結(jié)束!
*/
非阻塞代碼示例
var fs = require("fs"); // 獲取文件操作對(duì)象
// 阻塞函數(shù):還沒(méi)讀取完input.txt就先執(zhí)行下面console代碼,讀取完了再執(zhí)行function(err,data)函數(shù)
fs.readFile('input.txt', function (err, data) {
/*
如果在讀取文件過(guò)程中發(fā)生錯(cuò)誤,錯(cuò)誤 err 對(duì)象就會(huì)輸出錯(cuò)誤信息。
如果沒(méi)發(fā)生錯(cuò)誤,readFile 跳過(guò) err 對(duì)象的輸出,文件內(nèi)容就通過(guò)回調(diào)函數(shù)輸出。
*/
if (err) return console.error(err);
console.log(data.toString());
});
console.log("程序執(zhí)行結(jié)束!");
/*
程序執(zhí)行結(jié)束!
菜鳥教程官網(wǎng)地址:www.runoob.com
*/
四、Node.js 事件驅(qū)動(dòng)程序
語(yǔ)法分析
// 引入 events 模塊
var events = require('events');
// 創(chuàng)建 eventEmitter 對(duì)象
var eventEmitter = new events.EventEmitter();
// 綁定事件及事件的處理程序
eventEmitter.on('eventName', eventHandler);
// 觸發(fā)事件
eventEmitter.emit('eventName');
具體示例
// 引入 events 模塊
var events = require('events');
// 創(chuàng)建 eventEmitter 對(duì)象
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í)行完畢。");
/*
連接成功。
數(shù)據(jù)接收成功。
程序執(zhí)行完畢。
*/
五、Node.js 事件監(jiān)聽器
事件監(jiān)聽器就是回調(diào)函數(shù),event為事件綁定了回調(diào)函數(shù),當(dāng)事件發(fā)生時(shí)就會(huì)被回調(diào)函數(shù)監(jiān)聽到。
var events = require('events');
var emitter = new events.EventEmitter();
// event對(duì)象為someEvent綁定了監(jiān)聽器function,如果監(jiān)聽到了someEvent事件,就執(zhí)行方法
emitter.on('someEvent', function(arg1, arg2) {
console.log('listener1', arg1, arg2);
});
// event對(duì)象為someEvent綁定了監(jiān)聽器function,如果監(jiān)聽到了someEvent事件,就執(zhí)行方法
emitter.on('someEvent', function(arg1, arg2) {
console.log('listener2', arg1, arg2);
});
// 向event對(duì)象發(fā)送someEvent事件
emitter.emit('someEvent', 'arg1 參數(shù)', 'arg2 參數(shù)');
/*
listener1 arg1 參數(shù) arg2 參數(shù)
listener2 arg1 參數(shù) arg2 參數(shù)
*/
六、特殊的error事件
EventEmitter 定義了一個(gè)特殊的事件 error,它包含了錯(cuò)誤的語(yǔ)義,我們?cè)谟龅?異常的時(shí)候通常會(huì)觸發(fā) error 事件。
當(dāng) error 被觸發(fā)時(shí),EventEmitter 規(guī)定如果沒(méi)有響 應(yīng)的監(jiān)聽器,Node.js 會(huì)把它當(dāng)作異常,退出程序并輸出錯(cuò)誤信息。
我們一般要為會(huì)觸發(fā) error 事件的對(duì)象設(shè)置監(jiān)聽器,避免遇到錯(cuò)誤后整個(gè)程序崩潰。例如:
var events = require('events');
var emitter = new events.EventEmitter();
emitter.emit('error');
運(yùn)行時(shí)會(huì)顯示以下錯(cuò)誤:
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: Uncaught, unspecified 'error' event.
at EventEmitter.emit (events.js:50:15)
at Object.<anonymous> (/home/byvoid/error.js:5:9)
at Module._compile (module.js:441:26)
at Object..js (module.js:459:10)
at Module.load (module.js:348:31)
at Function._load (module.js:308:12)
at Array.0 (module.js:479:10)
at EventEmitter._tickCallback (node.js:192:40)
七、Node.js Buffer(緩沖區(qū))
JavaScript 語(yǔ)言自身只有字符串?dāng)?shù)據(jù)類型,沒(méi)有二進(jìn)制數(shù)據(jù)類型。
但在處理像TCP流或文件流時(shí),必須使用到二進(jìn)制數(shù)據(jù)。因此在 Node.js中,定義了一個(gè) Buffer 類,該類用來(lái)創(chuàng)建一個(gè)專門存放二進(jìn)制數(shù)據(jù)的緩存區(qū)。
Buffer與字符編碼
Buffer存儲(chǔ)二進(jìn)制數(shù)據(jù),但是可以通過(guò)制定編碼來(lái)輸出數(shù)據(jù)
const buf = Buffer.from('runoob', 'ascii');
// 輸出 72756e6f6f62
console.log(buf.toString('hex'));
// 輸出 cnVub29i
console.log(buf.toString('base64'));
/*
ascii - 僅支持 7 位 ASCII 數(shù)據(jù)。如果設(shè)置去掉高位的話,這種編碼是非??斓?。
utf8 - 多字節(jié)編碼的 Unicode 字符。許多網(wǎng)頁(yè)和其他文檔格式都使用 UTF-8 。
utf16le - 2 或 4 個(gè)字節(jié),小字節(jié)序編碼的 Unicode 字符。支持代理對(duì)(U+10000 至 U+10FFFF)。
ucs2 - utf16le 的別名。
base64 - Base64 編碼。
latin1 - 一種把 Buffer 編碼成一字節(jié)編碼的字符串的方式。
binary - latin1 的別名。
hex - 將每個(gè)字節(jié)編碼為兩個(gè)十六進(jìn)制字符。
*/
創(chuàng)建Buffer類
// 創(chuàng)建一個(gè)長(zhǎng)度為 10、且用 0 填充的 Buffer。
const buf1 = Buffer.alloc(10);
// 創(chuàng)建一個(gè)長(zhǎng)度為 10、且用 0x1 填充的 Buffer。
const buf2 = Buffer.alloc(10, 1);
// 創(chuàng)建一個(gè)長(zhǎng)度為 10、且未初始化的 Buffer。
// 這個(gè)方法比調(diào)用 Buffer.alloc() 更快,
// 但返回的 Buffer 實(shí)例可能包含舊數(shù)據(jù),
// 因此需要使用 fill() 或 write() 重寫。
const buf3 = Buffer.allocUnsafe(10);
// 創(chuàng)建一個(gè)包含 [0x1, 0x2, 0x3] 的 Buffer。
const buf4 = Buffer.from([1, 2, 3]);
// 創(chuàng)建一個(gè)包含 UTF-8 字節(jié) [0x74, 0xc3, 0xa9, 0x73, 0x74] 的 Buffer。
const buf5 = Buffer.from('tést');
// 創(chuàng)建一個(gè)包含 Latin-1 字節(jié) [0x74, 0xe9, 0x73, 0x74] 的 Buffer。
const buf6 = Buffer.from('tést', 'latin1');
/*
Buffer.alloc(size[, fill[, encoding]]): 返回一個(gè)指定大小的 Buffer 實(shí)例,如果沒(méi)有設(shè)置 fill,則默認(rèn)填滿 0
Buffer.allocUnsafe(size): 返回一個(gè)指定大小的 Buffer 實(shí)例,但是它不會(huì)被初始化,所以它可能包含敏感的數(shù)據(jù)
Buffer.allocUnsafeSlow(size)
Buffer.from(array): 返回一個(gè)被 array 的值初始化的新的 Buffer 實(shí)例(傳入的 array 的元素只能是數(shù)字,不然就會(huì)自動(dòng)被 0 覆蓋)
Buffer.from(arrayBuffer[, byteOffset[, length]]): 返回一個(gè)新建的與給定的 ArrayBuffer 共享同一內(nèi)存的 Buffer。
Buffer.from(buffer): 復(fù)制傳入的 Buffer 實(shí)例的數(shù)據(jù),并返回一個(gè)新的 Buffer 實(shí)例
Buffer.from(string[, encoding]): 返回一個(gè)被 string 的值初始化的新的 Buffer 實(shí)例
*/
寫入緩沖區(qū)
/*
string:寫入緩沖區(qū)的字符串
offset:開始寫入的索引值,默認(rèn)為0
length:寫入的字節(jié)數(shù),默認(rèn)為buffer.length
encoding:使用的編碼,默認(rèn)為utf-8
buf.write(string[, offset[, length]][, encoding])
*/
buf = Buffer.alloc(256);
len = buf.write("www.runoob.com");
console.log("寫入字節(jié)數(shù) : "+ len); // 寫入字節(jié)數(shù) : 14
讀取緩沖區(qū)
/*
encoding - 使用的編碼。默認(rèn)為 'utf8' 。
start - 指定開始讀取的索引位置,默認(rèn)為 0。
end - 結(jié)束位置,默認(rèn)為緩沖區(qū)的末尾。
buf.toString([encoding[, start[, end]]])
*/
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)); // 使用默認(rèn)的 'utf8' 編碼, 并輸出: abcde
/*
abcdefghijklmnopqrstuvwxyz
abcde
abcde
abcde
*/
緩沖區(qū)是有挺多方法的,這里只記錄一些常用的方法。
八、輸入輸出流 Stream
輸入流
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í)行完畢");
/*
程序執(zhí)行完畢
菜鳥教程官網(wǎng)地址:www.runoob.com
*/
輸出流
var fs = require("fs");
var data = '菜鳥教程官網(wǎng)地址:www.runoob.com';
// 創(chuàng)建一個(gè)可以寫入的流,寫入到文件 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í)行完畢");
/*
以上程序會(huì)將 data 變量的數(shù)據(jù)寫入到 output.txt 文件中。代碼執(zhí)行結(jié)果如下:
程序執(zhí)行完畢
寫入完成。
*/
九、Node.js 模塊系統(tǒng)
導(dǎo)出模塊
//hello.js
function Hello() {
var name;
this.setName = function(thyName) {
name = thyName;
};
this.sayHello = function() {
console.log('Hello ' + name);
};
};
module.exports = Hello; // 將函數(shù)Hello暴露出來(lái)
引入模塊
//main.js
var Hello = require('./hello');
hello = new Hello();
hello.setName('BYVoid');
hello.sayHello();
十、 Node.js 路由
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;
router.js 文件代碼
function route(pathname) {
console.log("About to route a request for " + pathname);
}
exports.route = route;
index.js 文件代碼
var server = require("./server");
var router = require("./router");
server.start(router.route);
運(yùn)行結(jié)果
$ node index.js
Server has started.
十一、GET/POST請(qǐng)求
獲取GET請(qǐng)求URL的參數(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請(qǐng)求內(nèi)容
var http = require('http');
var querystring = require('querystring');
var postHTML =
'<html><head><meta charset="utf-8"><title>菜鳥教程 Node.js 實(shí)例</title></head>' +
'<body>' +
'<form method="post">' +
'網(wǎng)站名: <input name="name"><br>' +
'網(wǎng)站 URL: <input name="url"><br>' +
'<input type="submit">' +
'</form>' +
'</body></html>';
http.createServer(function (req, res) {
var body = "";
req.on('data', function (chunk) {
body += chunk;
});
req.on('end', function () {
// 解析參數(shù)
body = querystring.parse(body);
// 設(shè)置響應(yīng)頭部信息及編碼
res.writeHead(200, {'Content-Type': 'text/html; charset=utf8'});
if(body.name && body.url) { // 輸出提交的數(shù)據(jù)
res.write("網(wǎng)站名:" + body.name);
res.write("<br>");
res.write("網(wǎng)站 URL:" + body.url);
} else { // 輸出表單
res.write(postHTML);
}
res.end();
});
}).listen(3000);
十二、Node.js 搭建Web服務(wù)器
server.js
var http = require('http');
var fs = require('fs');
var url = require('url');
// 創(chuàng)建服務(wù)器
http.createServer( function (request, response) {
// 解析請(qǐng)求,包括文件名
var pathname = url.parse(request.url).pathname;
// 輸出請(qǐng)求的文件名
console.log("Request for " + pathname + " received.");
// 從文件系統(tǒng)中讀取請(qǐ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);
// 控制臺(tái)會(huì)輸出以下信息
console.log('Server running at http://127.0.0.1:8080/');
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鳥教程(runoob.com)</title>
</head>
<body>
<h1>我的第一個(gè)標(biāo)題</h1>
<p>我的第一個(gè)段落。</p>
</body>
</html>
接著我們?cè)跒g覽器中打開地址:http://127.0.0.1:8080/index.html
十三、第一個(gè)Node.js Express 框架
Express 是一個(gè)簡(jiǎn)潔而靈活的 node.js Web應(yīng)用框架, 提供了一系列強(qiáng)大特性幫助你創(chuàng)建各種 Web 應(yīng)用,和豐富的 HTTP 工具。expressDemo.js
var express = require('express');
var app = express();
// 開啟服務(wù)之后,如果訪問(wèn)到了/,就發(fā)生下面的函數(shù)
app.get('/', function (req, res) {
res.send('Hello World');
})
// 監(jiān)聽器,監(jiān)聽到8081端口有動(dòng)靜就觸發(fā)回調(diào)函數(shù)
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例,訪問(wèn)地址為 http://%s:%s", host, port)
})
十四、Request對(duì)象和Response對(duì)象的具體介紹
Request 對(duì)象 - request 對(duì)象表示 HTTP 請(qǐng)求,包含了請(qǐng)求查詢字符串,參數(shù),內(nèi)容,HTTP 頭部等屬性。常見(jiàn)屬性有:
req.app:當(dāng)callback為外部文件時(shí),用req.app訪問(wèn)express的實(shí)例
req.baseUrl:獲取路由當(dāng)前安裝的URL路徑
req.body / req.cookies:獲得「請(qǐng)求主體」/ Cookies
req.fresh / req.stale:判斷請(qǐng)求是否還「新鮮」
req.hostname / req.ip:獲取主機(jī)名和IP地址
req.originalUrl:獲取原始請(qǐng)求URL
req.params:獲取路由的parameters
req.path:獲取請(qǐng)求路徑
req.protocol:獲取協(xié)議類型
req.query:獲取URL的查詢參數(shù)串
req.route:獲取當(dāng)前匹配的路由
req.subdomains:獲取子域名
req.accepts():檢查可接受的請(qǐng)求的文檔類型
req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages:返回指定字符集的第一個(gè)可接受字符編碼
req.get():獲取指定的HTTP請(qǐng)求頭
req.is():判斷請(qǐng)求頭Content-Type的MIME類型
Response 對(duì)象 - response 對(duì)象表示 HTTP 響應(yīng),即在接收到請(qǐng)求時(shí)向客戶端發(fā)送的 HTTP 響應(yīng)數(shù)據(jù)。常見(jiàn)屬性有:
res.app:同req.app一樣
res.append():追加指定HTTP頭
res.set()在res.append()后將重置之前設(shè)置的頭
res.cookie(name,value [,option]):設(shè)置Cookie
opition: domain / expires / httpOnly / maxAge / path / secure / signed
res.clearCookie():清除Cookie
res.download():傳送指定路徑的文件
res.get():返回指定的HTTP頭
res.json():傳送JSON響應(yīng)
res.jsonp():傳送JSONP響應(yīng)
res.location():只設(shè)置響應(yīng)的Location HTTP頭,不設(shè)置狀態(tài)碼或者close response
res.redirect():設(shè)置響應(yīng)的Location HTTP頭,并且設(shè)置狀態(tài)碼302
res.render(view,[locals],callback):渲染一個(gè)view,同時(shí)向callback傳遞渲染后的字符串,如果在渲染過(guò)程中有錯(cuò)誤發(fā)生next(err)將會(huì)被自動(dòng)調(diào)用。callback將會(huì)被傳入一個(gè)可能發(fā)生的錯(cuò)誤以及渲染后的頁(yè)面,這樣就不會(huì)自動(dòng)輸出了。
res.send():傳送HTTP響應(yīng)
res.sendFile(path [,options] [,fn]):傳送指定路徑的文件 -會(huì)自動(dòng)根據(jù)文件extension設(shè)定Content-Type
res.set():設(shè)置HTTP頭,傳入object可以一次設(shè)置多個(gè)頭
res.status():設(shè)置HTTP狀態(tài)碼
res.type():設(shè)置Content-Type的MIME類型
十五、Node.js Web路由示例
var express = require('express');
var app = express();
// 主頁(yè)輸出 "Hello World"
app.get('/', function (req, res) {
console.log("主頁(yè) GET 請(qǐng)求");
res.send('Hello GET');
})
// POST 請(qǐng)求
app.post('/', function (req, res) {
console.log("主頁(yè) POST 請(qǐng)求");
res.send('Hello POST');
})
// /del_user 頁(yè)面響應(yīng)
app.get('/del_user', function (req, res) {
console.log("/del_user 響應(yīng) DELETE 請(qǐng)求");
res.send('刪除頁(yè)面');
})
// /list_user 頁(yè)面 GET 請(qǐng)求
app.get('/list_user', function (req, res) {
console.log("/list_user GET 請(qǐng)求");
res.send('用戶列表頁(yè)面');
})
// 對(duì)頁(yè)面 abcd, abxcd, ab123cd, 等響應(yīng) GET 請(qǐng)求
app.get('/ab*cd', function(req, res) {
console.log("/ab*cd GET 請(qǐng)求");
res.send('正則匹配');
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例,訪問(wèn)地址為 http://%s:%s", host, port)
})
接下來(lái)你可以嘗試訪問(wèn) http://127.0.0.1:8081 不同的地址,查看效果。
十六、Node.js 靜態(tài)文件
Express 提供了內(nèi)置的中間件 express.static 來(lái)設(shè)置靜態(tài)文件如:圖片, CSS, JavaScript 等
你可以使用 express.static 中間件來(lái)設(shè)置靜態(tài)文件路徑。例如,如果你將圖片, CSS, JavaScript 文件放在 public 目錄下
讓我們?cè)傩薷南?“Hello World” 應(yīng)用添加處理靜態(tài)文件的功能。
var express = require('express');
var app = express();
// 表示可以訪問(wèn)這里面的資源,如果不添加這一句,去訪問(wèn)public的資源會(huì)發(fā)生錯(cuò)誤:Cannot GET /public/images/logo.png
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)用實(shí)例,訪問(wèn)地址為 http://%s:%s", host, port)
})
在瀏覽器中訪問(wèn) http://127.0.0.1:8081/public/images/logo.png
十七、前端與后端的數(shù)據(jù)交互(HTML與Node.js)
GET請(qǐng)求index.html代碼
<html>
<body>
<form action="http://127.0.0.1:8081/process_get" method="GET">
First Name: <input type="text" name="first_name"> <br>
Last Name: <input type="text" name="last_name">
<input type="submit" value="Submit">
</form>
</body>
</html>
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, function () {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例,訪問(wèn)地址為 http://%s:%s", host, port)
})
瀏覽器訪問(wèn) http://127.0.0.1:8081/index.html,向表單輸入數(shù)據(jù),并提交
POST請(qǐng)求index.html代碼
<html>
<body>
<form action="http://127.0.0.1:8081/process_post" method="POST">
First Name: <input type="text" name="first_name"> <br>
Last Name: <input type="text" name="last_name">
<input type="submit" value="Submit">
</form>
</body>
</html>
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, function () {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例,訪問(wèn)地址為 http://%s:%s", host, port)
})
瀏覽器訪問(wèn) http://127.0.0.1:8081/index.html,向表單輸入數(shù)據(jù),并提交
十八、Node.js 的RESTful API
舉個(gè)例子吧,我們對(duì)一個(gè)數(shù)據(jù)庫(kù)的CRUD,對(duì)應(yīng)的接口和訪問(wèn)URL如下
@RequestMapping("/add/User")
public Boolean addUser()
@RequestMapping("/delete/User")
public Boolean deleteUser()
@RequestMapping("/update/User")
public Boolean updateUser()
@RequestMapping("/get/User")
public User getUser()
使用REST API,在HTTP協(xié)議里面,四個(gè)表示操作方式的動(dòng)詞:GET、POST、PUT、DELETE。它們分別對(duì)應(yīng)四種基本操作:GET用來(lái)獲取資源,POST用來(lái)新建資源(也可以用于更新資源),PUT用來(lái)更新資源,DELETE用來(lái)刪除資源。
@RequestMapping("/User") // 使用POST請(qǐng)求
public Boolean addUser()
@RequestMapping("/User") // 使用DELET請(qǐng)求
public Boolean deleteUser()
@RequestMapping("/User") // 使用PUT請(qǐng)求
public Boolean updateUser()
@RequestMapping("/get/User") // 使用GET請(qǐng)求
public User getUser()
創(chuàng)建node.js代碼實(shí)例獲取用戶列表
var express = require('express');
var app = express();
var fs = require("fs");
app.get('/Users', function (req, res) {
fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
console.log( data );
res.end( data );
});
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("應(yīng)用實(shí)例,訪問(wèn)地址為 http://%s:%s", host, port)
})
在瀏覽器中訪問(wèn) http://127.0.0.1:8081/Users,結(jié)果如下所示:
{
"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
}
}
十九、Node.js 創(chuàng)建多進(jìn)程
Node 提供了 child_process 模塊來(lái)創(chuàng)建子進(jìn)程,方法有:
- exec - child_process.exec 使用子進(jìn)程執(zhí)行命令,緩存子進(jìn)程的輸出,并將子進(jìn)程的輸出以回調(diào)函數(shù)參數(shù)的形式返回。
- spawn - child_process.spawn 使用指定的命令行參數(shù)創(chuàng)建新進(jìn)程。
- fork - child_process.fork 是 spawn()的特殊形式,用于在子進(jìn)程中運(yùn)行的模塊,如 fork(‘./son.js’) 相當(dāng)于 spawn(‘node’, [‘./son.js’]) ,與spawn方法不同的是,fork會(huì)在父進(jìn)程與子進(jìn)程之間,建立一個(gè)通信管道,用于進(jìn)程之間的通信。
exec()方法
child_process.exec 使用子進(jìn)程執(zhí)行命令,緩存子進(jìn)程的輸出,并將子進(jìn)程的輸出以回調(diào)函數(shù)參數(shù)的形式返回。
console.log("進(jìn)程 " + process.argv[2] + " 執(zhí)行。" );
const fs = require('fs');
const child_process = require('child_process');
// 循環(huán)三次創(chuàng)建子線程執(zhí)行任務(wù)
for(var i=0; i<3; i++) {
// 子線程執(zhí)行如下任務(wù),然后將信息緩存起來(lái),等待下面任務(wù)執(zhí)行完畢
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);
});
// 子線程執(zhí)行結(jié)束的時(shí)候,在控制臺(tái)發(fā)出信息
workerProcess.on('exit', function (code) {
console.log('子進(jìn)程已退出,退出碼 '+code);
});
}
執(zhí)行以上代碼,輸出結(jié)果為:
$ node master.js
子進(jìn)程已退出,退出碼 0
stdout: 進(jìn)程 1 執(zhí)行。
stderr:
子進(jìn)程已退出,退出碼 0
stdout: 進(jìn)程 0 執(zhí)行。
stderr:
子進(jìn)程已退出,退出碼 0
stdout: 進(jìn)程 2 執(zhí)行。
stderr:
spawn() 方法
child_process.spawn 使用指定的命令行參數(shù)創(chuàng)建新進(jìn)程support.js 文件代碼:
console.log("進(jìn)程 " + 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.spawn('node', ['support.js', i]);
workerProcess.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
workerProcess.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
workerProcess.on('close', function (code) {
console.log('子進(jìn)程已退出,退出碼 '+code);
});
}
執(zhí)行以上代碼,輸出結(jié)果為:
$ node master.js stdout:
進(jìn)程 0 執(zhí)行。
子進(jìn)程已退出,退出碼 0
stdout: 進(jìn)程 1 執(zhí)行。
子進(jìn)程已退出,退出碼 0
stdout: 進(jìn)程 2 執(zhí)行。
子進(jìn)程已退出,退出碼 0
fork() 方法
child_process.spawn 使用指定的命令行參數(shù)創(chuàng)建新進(jìn)程support.js 文件代碼:
console.log("進(jìn)程 " + process.argv[2] + " 執(zhí)行。" );
master.js 文件代碼:
const fs = require('fs');
const child_process = require('child_process');
for(var i=0; i<3; i++) {
var worker_process = child_process.fork("support.js", [i]);
worker_process.on('close', function (code) {
console.log('子進(jìn)程已退出,退出碼 ' + code);
});
}
執(zhí)行以上代碼,輸出結(jié)果為:
$ node master.js
進(jìn)程 0 執(zhí)行。
子進(jìn)程已退出,退出碼 0
進(jìn)程 1 執(zhí)行。
子進(jìn)程已退出,退出碼 0
進(jìn)程 2 執(zhí)行。
子進(jìn)程已退出,退出碼 0
二十、Node.js 對(duì)MySQL CRUD
查詢數(shù)據(jù)
var mysql = require('mysql');
// 創(chuàng)建數(shù)據(jù)庫(kù)對(duì)象
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '123456',
port: '3306',
database: 'test'
});
// 連接數(shù)據(jù)庫(kù)
connection.connect();
// 創(chuàng)建SQL語(yǔ)句
var sql = 'SELECT * FROM websites';
// 執(zhí)行sql語(yǔ)句操作,并將結(jié)果放在result
connection.query(sql,function (err, result) {
if(err){
console.log('[SELECT ERROR] - ',err.message);
return;
}
console.log('--------------------------SELECT----------------------------');
console.log(result);
console.log('------------------------------------------------------------\n\n');
});
// 關(guān)閉數(shù)據(jù)庫(kù)連接
connection.end();
插入數(shù)據(jù)
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '123456',
port: '3306',
database: 'test'
});
connection.connect();
var addSql = 'INSERT INTO websites(Id,name,url,alexa,country) VALUES(0,?,?,?,?)';
var addSqlParams = ['菜鳥工具', 'https://c.runoob.com','23453', 'CN'];
//增
connection.query(addSql,addSqlParams,function (err, result) {
if(err){
console.log('[INSERT ERROR] - ',err.message);
return;
}
console.log('--------------------------INSERT----------------------------');
//console.log('INSERT ID:',result.insertId);
console.log('INSERT ID:',result);
console.log('-----------------------------------------------------------------\n\n');
});
connection.end();
更新數(shù)據(jù)
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-424417.html
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '123456',
port: '3306',
database: 'test'
});
connection.connect();
var modSql = 'UPDATE websites SET name = ?,url = ? WHERE Id = ?';
var modSqlParams = ['菜鳥移動(dòng)站', 'https://m.runoob.com',6];
//改
connection.query(modSql,modSqlParams,function (err, result) {
if(err){
console.log('[UPDATE ERROR] - ',err.message);
return;
}
console.log('--------------------------UPDATE----------------------------');
console.log('UPDATE affectedRows',result.affectedRows);
console.log('-----------------------------------------------------------------\n\n');
});
connection.end();
刪除數(shù)據(jù)
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-424417.html
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '123456',
port: '3306',
database: 'test'
});
connection.connect();
var delSql = 'DELETE FROM websites where id=6';
//刪
connection.query(delSql,function (err, result) {
if(err){
console.log('[DELETE ERROR] - ',err.message);
return;
}
console.log('--------------------------DELETE----------------------------');
console.log('DELETE affectedRows',result.affectedRows);
console.log('-----------------------------------------------------------------\n\n');
});
connection.end();
到了這里,關(guān)于【Node.JS】初入前端,學(xué)習(xí)node.js基本操作的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!