1. 程式人生 > >淺析node.js

淺析node.js

() 開發 gen web .get 服務器 有一個 生成 escape

  大家好,今天來給大家討論node.js這個東西,說起這個東西啊,可能大家已經很熟悉了,因為現在市場上運用的越來越廣泛,畢竟它的優點還是有目共睹的!

  那麽,什麽是node.js呢?官方給出了這樣的定義:“node.js是一個基於Chrome V8引擎的JavaScript運行環境。Node.js使用了一個事件驅動、非阻塞式I/O的模型,使其輕量又高效“。這樣我們就能知道node.js是一個運行環境,而且具有輕量又高效的特點。

  既然提到了運行環境,那麽我們都知道瀏覽器也是一個運行環境,他們之間有沒有區別呢?自然是有的,在瀏覽器安全環境下有一些安全性的限制,不允許調用底層的方法,但node環境允許調用底層的各種api,而且在node環境下我們是可以操作文件系統的(這個可厲害了!試想一下,如果瀏覽器能夠使用文件系統,那麽當你訪問一個惡意網站時)!

一般來說,node適合開發高並發的項目,一般在大型項目中作為中間層使用,搭node中間層的目的是解決高並發,同時解決性能問題,但是node本身也存在一些缺點:node處理大量計算時速度會比較慢!

  要想學好node,就一定要熟練使用npm,npm是一個node的包管理倉庫,是世界上最大的開放源代碼的生態系統,也是一個網站,也是一條命令

  這裏介紹一些node的使用方法,當然了,大家需要先安裝一下node,具體安裝方法可以百度上來看,很多,也很簡單!在此之前,我們要先說一下node中的模塊問題,node有很多自己的模塊,因為node遵循的是commonjs的規範,因此我們要使用內置模塊時直接通過require引用就好了,比如我們使用http模塊創建一個服務器

const http = require("http")

const server = http.createServer(req,res()=>{
   res.end("hello world") 
})
res.listen("9000")

除了內置模塊。npm上還有很多第三方模塊,我們可以通過下載來使用這些模塊,可以通過npm install 模塊名 --global(可以簡寫為-g)來進行全局下載,npm install 模塊 --save(-s)安裝項目依賴

  好了,說完模塊問題,我們就可以來進行正式的npm命令使用了,首先我們應該去官網註冊有個npm賬號,當我們寫了一個不錯的模塊時,想要把該模塊上傳到npm網站時我們就可以這樣操作

//首先在cmd中進去我們的項目文件夾
c/d/e/://進入什麽盤(c還是d還是e)
cd  file//進去你的模塊文件夾
npm  init

//執行完這行命令後,會生成一個package.json的文件夾,文件夾中的name名要唯一,當這個文件夾存在時node就是一個包了

npm  adduser 輸入賬號密碼

npm  publish  上傳模塊

然後別人就可以通過npm  install 模塊名來下載你的模塊了!

因為npm是國外的網站,可能有時候我們下載需要的資源時網速會有點那麽不盡人意,這個時候我們就需要用到nrm這個模塊了

npm install  nrm  -g//全局安裝

nrm  ls  //查看可以使用的源

nrm test  源名  //測試單個源的速度

nrm  use  源名  //切換到你要使用的源


//這樣我們就可以把源切換到下載速度較快的源,就會加快好多了

  關於yarn:

yarn類似於npm的替代品,與npm相差無幾,但是相比npm有以下幾個優點:

1>.yarn是異步的所以比npm快
2>.團隊編程中使用yarn,可以保證版本號一致,開發時不出錯
3>.本地的包會有緩存,安裝本本地存在的包時會非常快

值得註意的是用yarn下載模塊的時候是通過yarn add 模塊名 來下載的,而且不需要加-s。直接代表npm install 模塊名 --save

接下來我們來介紹一下node中常用的幾個模塊:

1.url模塊:

url.parse(urlString[, parseQueryString[, slashesDenoteHost]])
url.format(urlObject)
url.resolve(from, to)

代碼使用如下

const url=require("url");
//url.parse()解析url,返回值是URLobject;
Const    result=url.parse("https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=node&oq=node&rsv_pq=aea4b4650005e274&rsv_t=b6efVwyWo9RLoHnJougYq4rPh%2B83TZcEX%2BdoFLqN8zcpvB2fgErBjdboWPo&rqlang=cn&rsv_enter=0",true);
//urlformat.根據URLobject生成URL
const rs=url.format(result);
 console.log(rs);
//生成相對路徑或絕對路徑的一種方法
console.log(url.resolve("http://www.baidu.com/a/b/c","d"));
//網址是/a/b/c
//<a href="/d">跳轉到d</a>
//  結果是http://www.baidu.com/a/b/d
console.log(url.resolve("http://www.baudu.com/a/b/c","/d"));
//網頁地址是/a/b/c
// <a href="/d">跳轉到d</a>
//結果是http://www.baidu.com/d

2、Query String
querystring.escape(str)對給定的字符串進行編碼
querystring.parse(str[, sep[, eq[, options]]])要解析的url
querystring.stringify(obj[, sep[, eq[, options]]])把對象轉換成jQuery對象
querystring.unescape(str)對給定的str解碼
Querystring.js代碼:

const querystring = require("querystring");
const str = "name%dell!age%28!gender%male";
//querystring.parse 對querys字符串進行解析,seprator=&,equal=
const result = querystring.parse(str,"!","%");
//querystring.stringify 把對象轉化成query字符串
console.log(querystring.stringify(result, "!", "%"));
const newStr = "a=1=2=3";
console.log(querystring.unescape(querystring.escape(newStr)));

3、HTTP模塊

HTTP小爬蟲 cheerio Request方法(擴展)
http.js代碼

const http = require("http");//引入http核心模塊
const cheerio = require(cheerio);//引入cheerio
const fs = require("fs"); //
//因為大多數請求都是get請求且不帶請求主體,所以node.js提供了更便捷方法,該方法與http.requirest()唯一區別就是它設置請求方式為get自定調用req.end();
http.get("http://www.easyvoa.com", (res) => {//http發送一個get請求
    if(res.statusCode == 200) {//200頁面加載成功
        let str = "";
        res.setEncoding(utf8);//編碼避免出現亂碼
        res.on("data", (data) => {//監聽data
            str += data;
        })
        res.on("end", () => {//觸發end時間
            const $ = cheerio.load(str);//用了一個第三方模塊,它的感覺像是jQuery實際上不是。只是幫助我們從一個字符串裏找出我們想要的字符串。
            const titles = $(".title_a");把.title標簽裏面的內容存在titles
            let result = "";
            for (var i = 0; i < titles.length; i++) {
                result += titles.eq(i).text() + \n;
            }
            fs.writeFileSync("list.text", result);
        })
    }
})

4、event模塊

EventEmitter 事件的參數 只執行一個的事件監聽器

代碼如下:

const EventEmitter=require("events");//EventEmitter它大寫是因為events導出來的 是一個類,而類的首字母是大寫
  class Wang extends EventEmitter{}// 自己定義了一個類繼承了EvenEtmitter{}
  const wang=new Wang();//創建一個wang實例對象
  wang.on("change",()=>{//對象有一個on方法
      console.log("change");
  })
  //wang.once("change",()=>{//once只執行一次
  //console.log("haha");
  //})
  //wang.prependListener("change");
  //wang.removeAlListener("change");
wang.emit("change");//emit觸發事件

5、fs模塊

得到文件與目錄的信息:stat
創建一個目錄:mkdir
創建文件並寫入內容:writeFile,appendFile
讀取文件的內容:readFileSyn
列出目錄的東西:readdir
重命名目錄或文件:rename
刪除目錄與文件:rmdir,unlink

代碼如下:

const fs=require("fs");
    //得到文件與目錄的信息
// fs.stat("list.text",(err,stats)=>{
//     console.log(stats.isDirectory());
// })
      //創建一個目錄
// fs.mkdir("wang",(err)=>{
//     if(err){
//         console.log(error);
//     }
// })
        //創建文件並寫入內容
// fs.writeFile("lee.txt","content",(err)=>{
//     console.log(err);
// }      
fs.writeFileSync("lee1.txt","1111")  
fs.appendFileSync("lee1.txt","2222")
 console.log(123);
// fs.readFile("lee1.txt",(err,data)=>{
//    console.log(data);
//})
//fs.readdir("./",())
//fs.readFile("lee1.txt",(err,data)=>{
//    console.log(data);//<Buffer 31 31 31 31 32 32 32 32>
//})
    //列出目錄中的東西返回一個數組
//fs.readdir("./",(err,list)=>{
//    console.log(list);//返回一個數組
//})
// fs.rename("lee.txt","llelele.txt",()=>{})
//重命名目錄或文件[‘

 const read=fs.createReadStream("lee1.txt");
 const write=fs.createWriteStream("leecopy.txt");
 read.pipe(zlib.createGzip()).pipe(write);
Server.js
   const server http.createServer((req,res)={
     If(req.url!==”/favicon.ico”){
        //Es6的解構賦值:
       const {pathname,query}=url.parse(req.url,true);
       (相當於:
Pathname=url.parse(req.url,true).pathname;
Query=url.parse(req.url,true).query;
)
        If(req.url==”/”){//如果訪問的是根目錄則返回index
           res.end(“index”);
}
if(req.url==”/list”){//如果訪問的是list則返回list
           res.end(“list”);
}else{//否則返回404
   res.end(“404”);
}

}
console.log(req.url);
Res.end(“hello world”);
})
 Server.listen(“3000”);

6、關於socket:網絡上的兩個程序通過一個雙向的通信連接實現數據的交換,這個連接的一端稱為一個socket。持久連接,全雙工,雙向通信;常用於:消息提示,聊天工具
代碼:

(1)服務器端:server.js
//引入net模板,net中有socket
const net=require("net");
/*每個用戶的連接,即保存所有用戶*/
const clients=[];
//創建服務
const server=net.createServer();
//監聽,當服務器被連接的時候,將連接用戶保存在clients數組中
server.on("connection",(client)=>{  
    //當一個用戶連接進來時,我給用戶一個id
    //將用戶存入所有用戶這個數組中
    client.id=clients.length;
    clients.push(client);
    //設置編碼集合
    client.setEncoding("utf8");
    //監聽用戶是否給服務器發了這個數據
    //如果發送了數據,服務器要把數據轉發給其他所有用戶--->群聊,聊天室
    client.on("data",(data)=>{
        //將數據發送給其他所有用戶
        for(var i=0;i<clients.length;i++){
            //如果存在,發送數據
            if(clients[i]){
                //轉發其他用戶
                clients[i].write(data);
            }
        }
    })
    //監聽用戶是否退出群聊
    client.on("close",(data)=>{
        //如果退出,將對應id用戶移除
        clients[client.id]=null;
    })
    //監聽用戶連接是否失敗
    client.on("error",(data)=>{
        //如果失敗,將對應id用戶移除
        clients[client.id]=null;
    })
    
    

})
server.listen("9000","127.0.0.1");
(2)客戶端:client.js
//net中有socket
const net=require("net");
const readline=require("readline");
//創建一個客戶端
const client=new net.Socket();
//創建一個和命令行連接的接口(讀和寫)
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

//連接服務器
client.connect("9000","127.0.0.1");
//設置編碼集合(buffer數據)
client.setEncoding("utf8");
//服務器傳來數據,這裏做監聽
client.on("data",(data)=>{
    
    console.log(data);    
})
//寫一個數據,往服務器發送數據
client.write("w_juan");
//對命令行數的監聽
//監聽控制臺輸入的內容發送給服務器
rl.on("line",(input)=>{
    if(input==="quit"){
        //銷毀
        rl.close();
        client.destory();
    }else{
        client.write(input);
    }
})

7、websocket:

代碼如下:

1) 服務器端:
const WebSocket = require(ws);
const server = new WebSocket.Server({ port: 9000 });
const clients = [];
server.on(connection, (client) => {
    //存儲用戶
    client.id = clients.length;
    clients.push(client);
    client.on(message, (message) => {
        //一旦發送信息,將message傳過去
        for (var i = 0; i < clients.length; i++) {
            clients[i] && clients[i].send(message);
            /*if(clients[i]){
                //轉發其他用戶
                clients[i].send(message);
            }*/
        }
    });
    client.on(error, () => {
        clients[client.id] = null;
    });
    client.on(close, () => {
        clients[client.id] = null;
    });
});
(2)客戶端:
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>聊天室</title>
    </head>
    <body>
        <input type="text" id="input" />
        <button id="button" onclick="handleClick()">提交</button>
        <div id="div1"></div>
        <script type="text/javascript">
            var client = new WebSocket("ws://127.0.0.1:9000");
            input = document.getElementById("input");
            div1 = document.getElementById("div1");
            function handleClick() {
                client.send(input.value);
            }
            client.onmessage = function(e) {
                div1.innerHTML=e.data;
            }
        </script>
    </body>
</html>

好了,今天就先給大家寫這麽多吧,歡迎大家來交流!總之,node涵蓋了前端和後端的很多內容,要想學好node,我們要深入理解前後端進行轉換的思想,在學好js的基礎上,盡可能的理解後端的運作及思維!祝大家早日拿下nodejs!



淺析node.js