1. 程式人生 > >Node.js基本使用和語法

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”