注:需要有html和js的基礎(chǔ)
Hello world
首先销凑,我們來(lái)看一下之前的Hello world
var http = require("http"); // 引入http模塊
http.createServer( function(req,rsp) { // 創(chuàng)建http服務(wù)
rsp.writeHead(200,{'Content-Type': 'text/plain'}); // 添加響應(yīng)頭
rsp.end('Hello World\n'); // 結(jié)束響應(yīng)
}).listen(80); // 監(jiān)聽(tīng)80端口
console.log("Server started"); // 打印消息到控制臺(tái)
這是一個(gè)最基礎(chǔ)的,對(duì)所有的請(qǐng)求都返回“Hello World”少态,開(kāi)頭引入http模塊叛复,使用http對(duì)象創(chuàng)建一個(gè)http服務(wù)并監(jiān)聽(tīng)80端口,回調(diào)函數(shù)中有一個(gè)req和rsp表示客戶端瀏覽器的請(qǐng)求(request)和服務(wù)端的響應(yīng)(response)鄙皇,我們只需要將要響應(yīng)的數(shù)據(jù)放到rsp里面即可,使用end()方法結(jié)束鼻吮。
如何顯示一個(gè)html頁(yè)面
我們知道育苟,最基礎(chǔ)的靜態(tài)網(wǎng)站是將我們寫好的html文件發(fā)送給瀏覽器顯示,那么如何使用nodejs顯示html文件椎木?
我們?cè)陧?xiàng)目根目錄下創(chuàng)建一個(gè)index.html
<!DOCTYPE html>
<html>
<head>
<title>這是主頁(yè)</title>
</head>
<body>
< img src="tupian.jpg" >
</body>
</html>
在根目錄放置一張圖片tupian.jpg违柏。
根據(jù)前面的知識(shí)我們能猜到,我們只要將html文件讀出來(lái)寫入到res里面即可香椎,那么讀寫文件我們就需要引入fs模塊漱竖,代碼修改如下:
var http = require("http");
var fs = require("fs");
http.createServer( function(req,rsp) {
fs.readFile("index.html",function(err,data){ // 讀取文件
rsp.end(data.toString()); // 文件數(shù)據(jù)轉(zhuǎn)成字符串后寫入rsp
});
}).listen(80);
console.log("Server started");
在項(xiàng)目根目錄下重新啟動(dòng)node(控制臺(tái)Ctrl+c退出,重新node test.js)畜伐,訪問(wèn)http://www.localhost/后會(huì)發(fā)現(xiàn)如下頁(yè)面:
這里我們可以發(fā)現(xiàn)頁(yè)面是已經(jīng)加載出來(lái)了馍惹,但圖片卻無(wú)法顯示,但是我們直接用瀏覽器打開(kāi)index.html卻正常玛界,并且我們?cè)谟蛎竺婕尤魏螙|西都能顯示這個(gè)頁(yè)面万矾,這是為何?
頂層路由
我們?cè)趆ttp回調(diào)的時(shí)候添加打印req.url
var http = require("http");
var fs = require("fs");
http.createServer( function(req,rsp) {
console.log(req.url);
fs.readFile("index.html",function(err,data){
rsp.end(data.toString());
});
}).listen(80);
console.log("Server started");
刷新頁(yè)面后發(fā)現(xiàn)我們刷新一次卻響應(yīng)了三次:
從字面上看“/”應(yīng)該響應(yīng)我們的html頁(yè)面慎框;“/tupian.jpg”是我們html文件中的img標(biāo)簽發(fā)起的請(qǐng)求良狈,應(yīng)該響應(yīng)我們圖片資源,然而我們這里依然響應(yīng)了index.html這個(gè)頁(yè)面顯然是不對(duì)的笨枯;“/favicon.ico”是請(qǐng)求圖標(biāo)的薪丁,這里暫不關(guān)心。
既然這樣馅精,那我們是不是能通過(guò)url來(lái)分別響應(yīng)對(duì)應(yīng)的數(shù)據(jù)严嗜?
我們繼續(xù)修改代碼,添加一個(gè)switch來(lái)分別對(duì)相應(yīng)的請(qǐng)求做出對(duì)應(yīng)的響應(yīng):
var http = require("http");
var fs = require("fs");
http.createServer( function(req,rsp) {
console.log(req.url);
switch(req.url){
case "/":
rsp.setHeader("Content-Type","text/html;charset=UTF-8"); // 設(shè)置內(nèi)容類型為html洲敢,字符集為UTF-8
fs.readFile("index.html",function(err,data){
rsp.end(data.toString());
});
break;
case "/tupian.jpg":
rsp.setHeader("Content-Type","image/jpeg"); // 設(shè)置內(nèi)容類型為image/jpeg格式
fs.readFile("tupian.jpg",function(err,data){
rsp.end(data);
});
break;
default:
rsp.writeHead(200,{'Content-Type': 'text/plain'});
rsp.end("404");
break;
}
}).listen(80);
console.log("Server started");
重新啟動(dòng)后刷新頁(yè)面(每次修改js文件后都必須重新啟動(dòng)):
顯示已經(jīng)正常了漫玄,并且訪問(wèn)其它地址會(huì)返回404,這基礎(chǔ)的路由就已經(jīng)實(shí)現(xiàn)了压彭。
http請(qǐng)求
http請(qǐng)求分get和post兩種方式称近,這兩種都是上行請(qǐng)求,都是將數(shù)據(jù)從瀏覽器發(fā)送到服務(wù)器哮塞,只是攜帶參數(shù)的方式不一樣刨秆。get請(qǐng)求是將參數(shù)放在url里面(網(wǎng)址中‘?’之后的數(shù)據(jù)),post是將數(shù)據(jù)放在表單里面忆畅。get方式比較輕便衡未,post方式比較安全,可以上傳大數(shù)據(jù)塊家凯,比如說(shuō)上傳文件缓醋。
get請(qǐng)求
get請(qǐng)求的參數(shù)的獲得需要用url模塊解析url得到querystring,即可得到绊诲。我們?cè)傩陆ㄒ粋€(gè)“/get”路由送粱,用來(lái)接收get請(qǐng)求。
var url = require("url"); // 引入url模塊
...
switch(url.parse(req.url).pathname){ // 解析出url路徑(此時(shí)url帶了參數(shù)需要去除)
...
case "/get":
var query = url.parse(req.url,true).query; // 解析出querystring
//console.log(query);
rsp.writeHead(200,{'Content-Type': 'text/plain'});
rsp.end("名字:"+query.name+"\n年齡:"+query.age);
break;
...
}
...
然后我們?cè)L問(wèn)http://www.localhost/get?name=xiaoming&age=19就能得到以下結(jié)果:
post請(qǐng)求
由于nodejs的單線程的掂之,所以一但有大內(nèi)容持續(xù)傳輸將嚴(yán)重影響體驗(yàn)抗俄,但nodejs會(huì)將post請(qǐng)求進(jìn)行分包脆丁,每次只傳一點(diǎn)點(diǎn),以免阻塞其它用戶动雹。post請(qǐng)求是可以跨域(不同的網(wǎng)站)請(qǐng)求的槽卫,我們這里創(chuàng)建一個(gè)post.html存放一個(gè)表單,提交到http://www.localhost/post去胰蝠。在代碼中創(chuàng)建一個(gè)“/post”路由來(lái)接收post請(qǐng)求歼培。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>post請(qǐng)求</title>
</head>
<body>
<form action="http://www.localhost/post" method="post">
<input type="text" name="name"><br><br>
<input type="text" name="age"><br><br>
<input type="submit">
</form>
</body>
</html>
修改js文件
...
case "/post":
var ret = "";
req.on("data",function(chunk){ // 小包接收
ret += chunk;
});
req.on("end",function(chunk){ // 全部接收完畢
var obj = querystring.parse(ret.toString()); // querystring轉(zhuǎn)成對(duì)象
console.log(obj);
rsp.writeHead(200,{'Content-Type': 'text/plain'});
rsp.end("名字:"+obj.name+"\n年齡:"+obj.age);
});
break;
...
填寫表單
提交
源碼
nodejs的特性
1、nodejs是單線程的
nodejs的主流程只有一個(gè)線程在執(zhí)行茸塞,所以nodejs不適合做計(jì)算量大的項(xiàng)目躲庄,所有的耗時(shí)操作都是通過(guò)回調(diào)來(lái)實(shí)現(xiàn)的。也正因?yàn)槭菃尉€程的钾虐,所以占用資源相當(dāng)少噪窘。
但不是說(shuō)需要一個(gè)頁(yè)面響應(yīng)完后nodejs再響應(yīng)其它的,nodejs在每個(gè)回調(diào)的點(diǎn)都會(huì)切換執(zhí)行的事件禾唁,也就是說(shuō)如果請(qǐng)求不是特別頻繁的情況下用戶是沒(méi)有感覺(jué)的效览。但一但有一個(gè)用戶頁(yè)面奔潰了整個(gè)服務(wù)器就宕了。