Node.js基本使用和語法
Node.js語法
1.1Node.js基本語法
1.1.1HelloWorld,最簡單搭建一個伺服器
//require表示引包,引包就是引用自己的一個特殊功能
var http = require("http");
//建立伺服器,引數是一個回撥函式,表示如果有請求進來,要做什麼
var server = http.createServer(function(req,res){
//req表示請求,request; res表示響應,response
//設定HTTP頭部,狀態碼是200,檔案型別是html,字符集是utf8
res.writeHead(200,{"Content-type" :"text/html;charset=UTF-8"});
res.end("哈哈哈哈,我買了五個iPhone" + (1+2+3) + "s");
});
//執行伺服器,監聽3000埠(埠號可以任改,此時的是‘127.0.0.1’)
server.listen(3000,"127.0.0.1");
注意:res.end()的內容必須為字串
1.1.2執行Node.js
1.執行
Node.js是伺服器的程式,寫的js語句,都將執行在伺服器上。返回給客戶的,都是已經處理好的純html。
node [name].js
表示執行你自己的檔案,[name]就是你實際的檔名字,再開啟瀏覽器
2.修改
如果想修改程式,必須中斷當前執行的伺服器,重新node一次,重新整理,才行。
ctrl+c,就可以打斷掛起的伺服器程式。此時按上箭頭,能夠快速呼叫最近的node命令。
3.總結
你會發現,我們本地寫一個js,打死都不能直接拖入瀏覽器執行,但是有了node,我們任何一個js檔案,都可以通過node來執行。也就是說,node就是一個js的執行環境。
我們現在,要跑起來一個伺服器,這個伺服器的指令碼,要以.js儲存。是一個js檔案。用node命令執行這個js檔案罷了。
1.1.3簡單的案例演示
//require表示引包,引包就是引用自己的一個特殊功能
var http = require ("http");
var fs = require("fs");
//建立伺服器,引數是一個回撥函式,表示如果有請求進來,要做什麼
var server = http.createServer(function(req,res){
if(req.url == "/fang"){
fs.readFile("./test/xixi.html",function(err,data){
//req表示請求,request; res表示響應,response
//設定HTTP頭部,狀態碼是200,檔案型別是html,字符集是utf8
res.writeHead(200,{"Content-type":"text/html;charset=UTF-8"});
res.end(data);
});
}else if(req.url == "/yuan"){
fs.readFile("./test/haha.html",function(err,data){
//req表示請求,request; res表示響應,response
//設定HTTP頭部,狀態碼是200,檔案型別是html,字符集是utf8
res.writeHead(200,{"Content-type":"text/html;charset=UTF-8"});
res.end(data);
});
}else if(req.url == "/0.jpg"){
fs.readFile("./test/0.jpg",function(err,data){
//req表示請求,request; res表示響應,response
//設定HTTP頭部,狀態碼是200,檔案型別是html,字符集是utf8
res.writeHead(200,{"Content-type":"image/jpg"});
res.end(data);
});
}else if(req.url == "/bbbbbb.css"){
fs.readFile("./test/aaaaaa.css",function(err,data){
//req表示請求,request; res表示響應,response
//設定HTTP頭部,狀態碼是200,檔案型別是html,字符集是utf8
res.writeHead(200,{"Content-type":"text/css"});
res.end(data);
});
}else{
res.writeHead(404,{"Content-type":"text/html;charset=UTF-8"});
res.end("嘻嘻,沒有這個頁面呦");
}
});
//執行伺服器,監聽3000埠(埠號可以任改)
server.listen(3000,"127.0.0.1");
Node.js沒有根目錄的概念,因為它根本沒有任何的web容器!
讓node.js提供一個靜態服務,都非常難!
也就是說,node.js中,如果看見一個網址是
127.0.0.1:3000/fang
別再去想,一定有一個資料夾,叫做fang了。可能/fang的物理檔案,是同目錄的test.html
URL和真實物理檔案,是沒有關係的。URL是通過了Node的頂層路由設計,呈遞某一個靜態檔案的。
例如上面的例子就是訪問127.0.0.1:3000/fang時去讀”./test/haha.html”檔案。當然我們也可以去讀別的資料夾中的檔案。
1.1.4 HTTP模組
Node.js中,將很多的功能,劃分為了一個個mudule,大陸的書翻譯為模組;臺灣的書,翻譯為模組。
這是因為,有一些程式需要使用fs功能(檔案讀取功能),有一些不用的,所以為了效率,你用啥,你就require啥。
//這個案例簡單講解http模組
//引用模組
var http = require("http");
//建立一個伺服器,回撥函式表示接收到請求之後做的事情
var server = http.createServer(function(req,res){
//req引數表示請求,res表示響應
console.log("伺服器接收到了請求" + req.url);
res.end();
});
//監聽埠
server.listen(3000,"127.0.0.1");
設定一個響應頭:
res.writeHead(200,{"Content-Type":"text/plain;charset=UTF8"});
1.1.5 URL模組
我們現在來看一下req裡面能夠使用的東西。
最關鍵的就是req.url屬性,表示使用者的請求URL地址。所有的路由設計,都是通過req.url來實現的。
我們比較關心的不是拿到URL,而是識別這個URL。
識別URL,用到url模組
var http = require("http");
//引入url模組
var URL = require("url");
var server = http.createServer(function(req,res){
//不處理小圖示(瀏覽器地址旁邊的小圖示)
if(req.url == "/favicon.ico"){
return;
}
//url.parse()可以將一個完整的URL地址,分為很多部分:
//host、port、pathname、path、query
var pathname = URL.parse(req.url).pathname;
//url.parse()如果第二個引數是true,那麼就可以將所有的查詢變為物件
//就可以直接打點得到這個引數
var query = URL.parse(req.url,true).query;
var url = URL.parse(req.url,true)
console.log(url);
res.end();
});
server.listen(3000,"127.0.0.1");
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '',
query: {},
pathname: '/hcd?name=1',
path: '/hcd?name=1',
href: '/hcd?name=1'
}
1.1.5.2URL模組的簡單案例
將表單提交後,獲取提交的資料
Form.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<form action="http://127.0.0.1:3000/" method="GET">
<input type="text" name="name" /> <br />
<input type="text" name="age" /> <br />
<input type="radio" name="sex" value="男"/> 男
<input type="radio" name="sex" value="女"/> 女
<br />
<input type="submit">
</form>
</body>
</html>
注意input的name屬性,URL.parse(req.url,true).query物件就是通過name屬性找屬性值的。
Node.js:
var http = require("http");
var URL = require("url");
var server = http.createServer(function(req,res){
console.log(URL.parse(req.url,true))
//得到查詢部分,由於寫了true,那麼就是一個物件,query是提交的資料集合的物件
var queryObj = URL.parse(req.url,true).query;
var name = queryObj.name;
var age = queryObj.age;
var sex = queryObj.sex;
res.end("伺服器收到了表單請求" + name + age + sex);
});
server.listen(3000,"127.0.0.1");
執行程式碼:
執行結果:
首先我們來看這時的URL物件:
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?name=haochangdi&age=24&sex=%E7%94%B7',
query: { name: 'haochangdi', age: '24', sex: '男' },
pathname: '/',
path: '/?name=haochangdi&age=24&sex=%E7%94%B7',
href: '/?name=haochangdi&age=24&sex=%E7%94%B7'
}
可以看到漢字‘男’被編碼了,並且query屬性是傳遞的資料的物件
頁面顯示:
01—案例6
1.1.6 router
由上面的URL模組我們知道通過req.url可以獲得請求的地址,下面我們來做一個路由案例
var http = require("http");
var server = http.createServer(function(req,res){
//得到url
var userurl = req.url;
res.writeHead(200,{"Content-Type":"text/html;charset=UTF8"})
//如果請求的地址為"/student"
if(userurl == "/student"){
res.end("student");
//如果請求的地址為"/teacher"
}else if(userurl == "/teacher"){
res.end("teacher");
//如果請求的地址沒有
}else{
res.end("404");
}
});
server.listen(3000,"127.0.0.1");
結果為:
訪問student:
訪問teacher:
訪問不存在的地址:
[01—案例7](https://github.com/haochangdi123/cleanUP-Node.js/tree/master/01)
1.1.7 fs模組
0.注意事項:
fs建立或者讀取檔案時是以cmd中的入口檔案為基本的,比如:
我們在cmd中執行:node 01.js
那麼我們任何檔案中用到fs時都是以01.js問基準找檔案的,比如在bar.js中找foo.js是‘./test/fss.js’
所以我們一般fs時是以——dirname這樣的絕對路徑的方式找檔案的。
1. 建立資料夾
fs. mkdir()建立資料夾
var http = require("http");
var fs = require("fs");
var server = http.createServer(function(req,res){
//不處理小圖示
if(req.url == "/favicon.ico"){
return;
}
//在此node.js檔案的同級album資料夾下建立一個aaa資料夾
fs.mkdir("./album/aaa");
});
server.listen(3000,"192.168.41.30");
2.檢測檔案狀態
fs.stat(path, callback) 檢視path路徑的檔案的狀態,callback為檢視完後的回撥函式
var http = require("http");
var fs = require("fs");
var server = http.createServer(function(req,res){
//不處理小圖示
if(req.url == "/favicon.ico"){
return;
}
//stat檢測狀態
fs.stat("./album/bbb",function(err,data){
//檢測這個路徑,是不是一個資料夾,返回true或false
console.log(data.isDirectory());
//檢測這個路徑,是不是一個檔案,返回true或false
console.log(data.isFile());
});
});
server.listen(3000,"127.0.0.1");
3.讀取檔案或者資料夾
讀取檔案:
fs.readFile('/etc/passwd', (err, data) => {
if (err) throw err;
console.log(data);
});
讀取資料夾:
fs.readdir(‘/etc/hcd’, (err, data) => {
if (err) throw err;
console.log(data);
});
4.更改檔案的名字
fs.rename([oldpath],[newpath],callback)
5.簡單案例—列舉album資料夾中的所有的檔案
先看一下檔案結構:
假設我們寫node.js的檔案就是01.js,而album檔案是和01.js平級的。album檔案中有aaa,ccc資料夾,還有多張圖片檔案,我們只將資料夾列舉出出來
平時習慣的錯誤寫法:
var http = require("http");
var fs = require("fs");
var server = http.createServer(function(req,res){
//不處理小圖示
if(req.url == "/favicon.ico"){
return;
}
//儲存所有的資料夾
var wenjianjia = [];
//stat檢測狀態
fs.readdir("./album",function(err,files){
//files是個檔名的陣列,並不是檔案的陣列,表示./album這個資料夾中的所有東西
//包括檔案、資料夾
for(var i = 0 ; i < files.length ;i++){
var thefilename = files[i];
//又要進行一次檢測
fs.stat("./album/" + thefilename , function(err,stats){
//如果他是一個資料夾,那麼輸出它:
if(stats.isDirectory()){
wenjianjia.push(thefilename);
}
//看每一次迴圈出的陣列是怎樣的,可以不要,直接最後輸出
console.log(wenjianjia);
});
}
});
});
server.listen(3000,"127.0.0.1");
結果:
會發現和我們想要的結果是不一樣的,這是因為node.js是非同步的,單執行緒非阻塞I/O,導致出錯(把每一次遍歷的結果都cosole是為了看的更清楚),我們可以利用(function(){})()這樣的立即執行函式解決,或者利用ES6的語法,使用let解決
01—案例11
正確的:
var http = require("http");
var fs = require("fs");
var server = http.createServer(function(req,res){
//不處理收藏夾小圖示
if(req.url == "/favicon.ico"){
return;
}
//遍歷album裡面的所有檔案、資料夾
fs.readdir("./album/",function(err,files){
//files : ["0.jpg","1.jpg" ……,"aaa","bbb"];
//files是一個存放檔案(夾)名的陣列
//存放資料夾的陣列
var wenjianjia = [];
//迭代器就是強行把非同步的函式,變成同步的函式
//1做完了,再做2;2做完了,再做3
(function iterator(i){
//遍歷結束
if(i == files.length){
console.log(wenjianjia);
return;
}
fs.stat("./album/" + files[i],function(err,stats){
//檢測成功之後做的事情
console.log(stats)
if(stats.isDirectory()){
//如果是資料夾,那麼放入陣列。不是,什麼也不做。
wenjianjia.push(files[i]);
}
iterator(i+1);
});
})(0);
});
res.end();
});
server.listen(3000,"127.0.0.1");
1.1.8 path模組
path.extname() 方法返回 path 的副檔名,
即從 path 的最後一部分中的最後一個 .(句號)字元到字串結束。 如果 path 的最後一部分沒有 . 或 path 的檔名(見 path.basename())的第一個字元是 .,則返回一個空字串。
path.extname('index.html');
// 返回: '.html'
path.extname('index.coffee.md');
// 返回: '.md'
path.extname('index.');
// 返回: '.'
path.extname('index');
// 返回: ''
path.extname('.index');
// 返回: ''
1.1.9一個比較完整的靜態資源案例
檔案的目錄結構:
var http = require("http");
var url = require("url");
var fs = require("fs");
var path = require("path");
http.createServer(function(req,res){
//得到使用者的路徑
var pathname = url.parse(req.url).pathname;
//預設首頁
if(pathname == "/"){
pathname = "index.html";
}
//拓展名
var extname = path.extname(pathname);
//真的到檔案的實際地址去讀取這個檔案
fs.readFile("./static/" + pathname,function(err,data){
if(err){
//如果此檔案不存在,就應該用404返回
fs.readFile("./static/404.html",function(err,data){
res.writeHead(404,{"Content-type":"text/html;charset=UTF8"});
res.end(data);
});
return;
};
//MIME型別,就是
//網頁檔案: text/html
//jpg檔案 : image/jpg
var mime = getMime(extname);
res.writeHead(200,{"Content-type":mime});
res.end(data);
});
}).listen(3000,"127.0.0.1");
function getMime(extname){
switch(extname){
case ".html" :
return "text/html";
break;
case ".jpg" :
return "image/jpg";
break;
case ".css":
return "text/css";
break;
}
}
結果就是在讀取http://127.0.0.1:3000/路徑時回去讀取”./static/index.html”