內容:css
1.node.js介紹html
2.node.js內置經常使用模塊前端
3.node.js數據交互node
1、node.js介紹python
(1)node.js特色jquery
與其餘語言相比,有如下優勢:web
固然,也有缺點:好比說庫支持不如Java豐富,和js同樣是單線程單進程ajax
(2)node.js安裝算法
下載對應你係統的Node.js版本:https://nodejs.org/en/download/,選安裝目錄進行安裝便可
安裝完畢測試以下:數據庫
(3)node.js用處
(4)運行node
建立一個node文件夾,而後在文件夾下寫入1.js:
1 let a = 12; 2 let b = 5; 3 4 console.log(a+b)
而後在命令行中進入node目錄下運行該文件:node 1.js 注:node運行文件:node xxx.js
運行結果以下:
2、node.js內置經常使用模塊
1.斷言——assert
1 const assert = require("assert") 2 3 function sum(a, b){ 4 // assert(判斷, "xxx") 判斷爲假輸出後面的信息 5 assert(arguments.length==2, "必須傳兩個參數") 6 assert(typeof a == 'number', "第一個參數必須是數字") 7 assert(typeof b == 'number', "第二個參數必須是數字") 8 9 return a+b 10 } 11 12 console.log(sum(2, 5)) 13 // 執行下面人任意一句將報錯: 14 // console.log(sum(2, '1')) 15 // console.log(sum(3))
2.Buffer和File System模塊
file system使用實例:
1 const fs = require("fs") 2 3 // 讀取文件 4 fs.readFile('1.txt', function(err, data){ 5 if(err){ 6 console.log("有錯!"); 7 } else { 8 console.log(data); 9 console.log(data.toString()); 10 } 11 12 }) 13 14 // 寫文件 15 fs.writeFile('2.txt', 'xxx', function(err){ 16 if (err) { 17 console.log(err); 18 } else { 19 console.log("成功!"); 20 } 21 })
注意:圖片不要將二進制轉成字符串,這樣作會致使圖片格式丟失
獲取文件詳細信息:
1 const fs = require('fs') 2 3 fs.stat('1.txt', function (err, stat) { 4 if(err){ 5 console.log('獲取文件信息失敗') 6 } else{ 7 console.log(stat) // detail info 8 console.log(stat.mtime.toGMTString()) // 修改時間 9 } 10 })
Buffer基礎使用:
1 let a = new Buffer('abc'); 2 let b = new Buffer('ddd'); 3 console.log(a, b) 4 // <Buffer 61 62 63> <Buffer 64 64 64> 5 6 let c = Buffer.concat([a, b]); 7 console.log(c); 8 // <Buffer 61 62 63 64 64 64>
Buffer數據操做:
1 // 查找 2 let a=new Buffer('abccc-=-dddder-=-qwerqwer'); 3 console.log(a.indexOf('-=-')); 4 5 // 截取 6 let b=new Buffer('abccc-=-dddder-=-qwerqwer'); 7 console.log(b.slice(0, 5).toString()); 8 9 // 切分 --> 目前buffer自帶的操做中沒有能夠直接用的split 10 let c=new Buffer('abccc-=-dddder-=-qwerqwer'); 11 12 Buffer.prototype.split=Buffer.prototype.split||function (c){ // 若是buffer有split就用buffer自帶的split,沒有就用下面的函數 13 let arr=[]; 14 15 let cur=0; 16 let n=0; 17 while((n=this.indexOf(c, cur))!==-1){ 18 arr.push(this.slice(cur, n)); 19 cur=n+c.length; 20 } 21 22 arr.push(this.slice(cur)); 23 24 return arr; 25 }; 26 27 let arr=c.split('-=-'); 28 console.log(arr); 29 console.log(arr.map(buffer=>buffer.toString()));
3.C++ Addons - 用C語言/C++寫插件給node用
4.多進程
理論上JavaScript是單進程單線程的,能夠經過如下模塊實現多進程:
注:node中沒有多線程的直接實現(爲了考慮安全性、應用性)
(1)進程與線程
(2)進程之間的通訊方法
(3)詳細用法
詳細用法見:http://www.javashuo.com/article/p-tnikywxl-bc.html
5.Crypto——散列、簽名
crypto模塊提供了md五、sha算法,主要用來進行加密(實質上是散列)、簽名
普通加密:
1 const crypto = require('crypto') 2 3 let obj = crypto.createHash('sha1') 4 // 或者用md5加密: 5 // let obj = crypto.createHash('md5') 6 7 obj.update('123456') 8 9 console.log(obj.digest('hex')) # 以16進制輸出數據
二次加密並加鹽:
1 const crypto = require('crypto') 2 3 function md5(str){ 4 let obj = crypto.createHash('md5') 5 obj.update(str) 6 7 return obj.digest('hex') 8 } 9 10 // 二級加密並加鹽 11 console.log(md5(md5('123456') + 'asdfghjklzxcvbnm,./' ))
6.http
下面是用http模塊搭建簡單服務器的大體過程:
最簡單的服務器:
1 const http = require("http") 2 3 let server = http.createServer(function(req, res){ 4 // 路由處理 5 switch(req.url){ 6 case '/aaa': 7 res.write('abc'); 8 break; 9 case '/bbb': 10 res.write('dddd'); 11 break; 12 case '/1.html': 13 res.write('<html><head></head><body>sdfasfasf</body></html>'); 14 break; 15 } 16 res.end() 17 }); 18 19 // 監聽 20 server.listen(8080)
先後端代碼分離的服務器(前端代碼存在www文件夾下):
1 const http=require('http'); 2 const fs=require('fs'); 3 4 let server=http.createServer(function(req, res){ 5 fs.readFile(`www${req.url}`, function(err, data){ 6 if(err){ 7 res.write('404'); // 404頁面 8 }else{ 9 res.write(data); 10 } 11 res.end(); 12 }); 13 }); 14 15 server.listen(8080);
注意:fs.readFile是一個異步操做,必須將res.end()放在readFile內,若是放在readFile外面會致使如下錯誤:
這個錯誤是由於程序不會等readFile執行完就會執行後面的end,所以要將end放在readFile內纔會在讀完文件後執行end
7.OS和Path
1 const os=require('os'); 2 const path=require('path'); 3 4 // 輸出CPU信息: 5 console.log(os.cpus()); 6 7 // 路徑相關: 8 let str='/var/local/www/aaa/1.png'; 9 //dirname -> 文件夾路徑 10 //basename -> 文件名 11 //extname -> 拓展名 12 console.log(path.dirname(str)); // /var/local/www/aaa 13 console.log(path.basename(str)); // 1.png 14 console.log(path.extname(str)); // .png
8.Events事件隊列
(1)機制原理
Nodejs的大部分核心API都是基於異步事件驅動設計的,全部能夠分發事件的對象都是EventEmitter類的實例。
你們知道,因爲nodejs是單線程運行的,因此nodejs須要藉助事件輪詢,不斷去查詢事件隊列中的事件消息,而後執行該事件對應的回調函數,有點相似windows的消息映射機制
(2)使用實例
1 const Event = require("events").EventEmitter 2 3 let ev = new Event() 4 5 // 一、監聽(接受) 6 ev.on('msg', function(a, b, c){ 7 console.log('收到了msg事件', a, b, c); 8 }) 9 10 // 二、派發(發送) 11 ev.emit('msg', 12, 5, 98)
(3)注意
大多數時候咱們不會直接使用 EventEmitter,而是在對象中繼承它。包括 fs、net、 http 在內的,只要是支持事件響應的核心模塊都是 EventEmitter 的子類
9.Query Strings和URL
(1)Query Strings
Query Strings:查詢字符串,url中的?以後的字符串即爲Query Strings
好比www.xxx.com/find?s=k&wd=123中的查詢字符串就是 s=k&wd=123
querystring實例:
1 const querystring = require("querystring") 2 3 // url: www.xxx.com/find?s=k&wd=123 4 let obj = querystring.parse("s=k&wd=123") 5 6 console.log(obj) 7 // 解析結果: { s: 'k', wd: '123' }
(2)URL
url模塊和querystring模塊不一樣之處:url模塊解析整個url,而querystring只能解析url中問號以後的字符串
實例:
1 const url = require("url") 2 3 let obj = url.parse("www.xxx.com/find?s=k&wd=123") 4 5 console.log(obj) 6 /* 7 輸出結果: 8 Url { 9 protocol: null, 10 slashes: null, 11 auth: null, 12 host: null, 13 port: null, 14 hostname: null, 15 hash: null, 16 search: '?s=k&wd=123', 17 query: 's=k&wd=123', 18 pathname: 'www.xxx.com/find', 19 path: 'www.xxx.com/find?s=k&wd=123', 20 href: 'www.xxx.com/find?s=k&wd=123' 21 } 22 */
注意:也能夠像下面同樣指定將query也一併解析
1 const url = require("url") 2 3 let obj = url.parse("www.xxx.com/find?s=k&wd=123", true) 4 5 console.log(obj) 6 /* 7 輸出結果: 8 Url { 9 protocol: null, 10 slashes: null, 11 auth: null, 12 host: null, 13 port: null, 14 hostname: null, 15 hash: null, 16 search: '?s=k&wd=123', 17 query: { s: 'k', wd: '123' }, 18 pathname: 'www.xxx.com/find', 19 path: 'www.xxx.com/find?s=k&wd=123', 20 href: 'www.xxx.com/find?s=k&wd=123' 21 } 22 */
10.網絡相關模塊
DNS解析實例:
1 const dns = require("dns") 2 3 dns.resolve("baidu.com", function(err, res){ 4 if(err){ 5 console.log("解析失敗") 6 } else { 7 console.log(res) 8 } 9 10 }) 11 12 // 結果: [ '220.181.57.216', '123.125.115.110' ]
11.流操做——Stream
(1)什麼是流
連續數據都是流:好比說視頻流、網絡流、文件流、語音流
(2)Stream具體操做
讀取寫入文件:
1 const fs = require('fs') 2 3 let rs = fs.createReadStream('1.txt') // 讀取流 4 let ws = fs.createWriteStream('2.txt') // 寫入流 5 6 rs.pipe(ws) 7 8 // 異常處理 9 rs.on('error', function (error) { 10 console.log('讀取失敗!') 11 }) 12 13 // 讀取完成 及 寫入完成 14 rs.on('end', function () { 15 console.log('讀取完成!') 16 }) 17 18 ws.on('finish', function () { 19 console.log('寫入完成!') 20 })
12.TLS/SSL
用於加密、安全
13.ZLIB
用於壓縮 - gz壓縮
zlib模塊使用實例:
1 const zlib = require('zlib') 2 const fs = require('fs') 3 4 let rs = fs.createReadStream('jQuery.js') 5 let ws = fs.createWriteStream('jQuery.js.gz') 6 7 let gz = zlib.createGzip() 8 9 rs.pipe(gz).pipe(ws) 10 11 // 異常處理 12 rs.on('error', function (error) { 13 console.log('讀取失敗!') 14 }) 15 16 // 讀取完成 及 寫入完成 17 rs.on('end', function () { 18 console.log('讀取完成!') 19 }) 20 21 ws.on('finish', function () { 22 console.log('寫入完成!') 23 })
3、node.js數據交互
web服務器三大任務:返回文件(html、css、圖片等)、數據交互(get、post)、數據庫,下面的部分將圍繞返回文件及數據交互展開
1.返回文件
返回文件可使用node.js中的fs模塊,實例以下:
1 const fs = require("fs") 2 3 fs.readFile('1.txt', function(err, data){ 4 if(err){ 5 console.log("有錯!"); 6 } else { 7 console.log(data); // 二進制 Buffer -> 能夠直接把這樣的數據返回給前端(圖片只能返回二進制,返回字符串將使圖片失效) 8 console.log(data.toString()); 9 } 10 11 })
2.數據交互 - get和post和文件上傳
(1)設置header
簡單設置header:
1 const http=require('http'); 2 const fs=require('fs'); 3 4 let server=http.createServer(function(req, res){ 5 fs.readFile(`www${req.url}`, function(err, data){ 6 if(err){ 7 // 返回404 8 res.writeHeader(404); // header 9 res.write('Not Found'); // body 10 }else{ 11 res.write(data); 12 } 13 res.end(); 14 }); 15 }); 16 17 server.listen(8080);
(2)get數據處理
get表單:
1 <form action="http://localhost:8080/aaa" method="get"> 2 用戶:<input type="text" name="user" /><br> 3 密碼:<input type="password" name="pass" /><br> 4 <input type="submit" value="提交"> 5 </form>
後端node:
1 const http=require('http') 2 const url=require('url') 3 4 let server=http.createServer(function(req, res){ 5 let {pathname, query} = url.parse(req.url, true) 6 console.log(pathname) // -> /xxx的形式 7 console.log(query) // -> { user: 'xxx', pass: 'xxx' }的形式 8 9 res.end() 10 }) 11 12 server.listen(8080)
(3)post數據處理
post表單(注意get和post請求能夠同時提交):
1 <form action="http://localhost:8080/aaa?id=12&a=55" method="post"> 2 用戶:<input type="text" name="user" /><br> 3 密碼:<input type="password" name="pass" /><br> 4 <input type="submit" value="提交"> 5 </form>
後端node:
1 const http=require('http') 2 const querystring=require('querystring') 3 4 let server=http.createServer(function(req, res){ 5 let str='' 6 7 // 有一個段到達了 8 req.on('data', function(data){ 9 str+=data 10 }) 11 12 // 結束了 13 req.on('end', function(){ 14 let post=querystring.parse(str) 15 console.log(str) 16 console.log(post) 17 }) 18 19 res.end() 20 }) 21 22 server.listen(8080)
注意:url和querystring的不一樣之處:
1 // url解析整個url
2 url.parse("www.xxx.com/aaa/bbb?a=12&b=5")
3 url.parse("/aaa/bbb?a=12&b=5") 4 // 另外加上true表示進一步解析query參數(不加就默認不進一步解析query): 5 url.parse("/aaa/bbb?a=12&b=5", true) 6 -> 7 { 8 、、、 9 "query": {a: 12, b: 5} 10 、、、 11 } 12 13 // querystring解析數據 14 querystring.parse("a=12&b=5")
(4)get和post數據一塊處理
前端仍是使用前面的get表單和post表單
後端node:
1 const http=require('http'); 2 const url=require('url'); 3 const querystring=require('querystring'); 4 5 let server=http.createServer((req, res)=>{ 6 // GET 7 let {pathname, query}=url.parse(req.url, true); 8 9 // POST 10 let str=''; 11 req.on('data', function(data){ 12 str+=data; 13 }); 14 req.on('end', function(){ 15 let post=querystring.parse(str); 16 17 console.log(pathname, query, post); 18 }); 19 20 res.end() 21 }); 22 23 server.listen(8080);
注意:在一個表單中能夠get請求能夠和post請求同時發
(5)文件上傳
前端代碼:
1 <form action="" method="post" enctype="multipart/form-data"> 2 <input type="file" name="upload-file"> 3 <input type="submit" value="上傳文件"> 4 </form> 5 6 注意: 7 上傳文件時表單中的enctype="multipart/form-data"必需要寫 8 input(file)必需要有name
後端可使用fs中的readFile和writeFile實現(讀取完上傳的文件後保存)
這樣作有弊端:
更好的方法:使用流,實例見後面的文件上傳實例
3.數據交互實例 - 登錄註冊簡單實現
(1)基本原理
1 // GET數據 -> 在url中 2 let {pathname, query} = url.parse(req.url, true) // 請求的地址及?以後的參數 3 4 // POST數據 -> 在body裏 比較大 5 let str = '' 6 req.on('data', function(data){ 7 str += data // post提交的數據 8 }) 9 10 req.end('end', function(err){ 11 let post = querystring.parse(str) // 解析提交的數據(字符串->對象) 12 })
(2)前端代碼
1 <!-- author: wyb --> 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <meta charset="UTF-8"> 6 <title>登錄</title> 7 <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> 8 </head> 9 <body> 10 11 用戶名: <input type="text" id="user"> <br> 12 密碼: <input type="password" id="pass"> <br> 13 <input type="button" value="註冊" id="btn1"> 14 <input type="button" value="登錄" id="btn2"> 15 16 <script> 17 /* 18 // 先後端接口: 19 用戶註冊: 20 /reg?user=xxx&pass=xxx 21 =>{error: 0, msg: '說明'} 22 23 用戶登錄: 24 /login?user=xxx&pass=xxx 25 =>{error: 0, msg: '說明'} 26 */ 27 $(function () { 28 // 註冊 29 $('#btn1').click(function () { 30 $.ajax({ 31 url: '/reg', 32 data: {user: $('#user').val(), pass: $('#pass').val()}, 33 dataType: 'json', 34 success(data){ 35 if(data.error){ 36 alert("錯了: " + data.msg) 37 } else { 38 alert("註冊成功") 39 } 40 }, 41 error(){ 42 alert("錯了") 43 } 44 }) 45 }) 46 47 // 登錄 48 $('#btn2').click(function () { 49 $.ajax({ 50 url: '/login', 51 data: {user: $('#user').val(), pass: $('#pass').val()}, 52 dataType: 'json', 53 success(data){ 54 if(data.error){ 55 alert("錯了: " + data.msg) 56 } else { 57 alert("登錄成功") 58 } 59 }, 60 error(){ 61 alert("錯了") 62 } 63 }) 64 }) 65 }) 66 </script> 67 68 </body> 69 </html>
(3)後端代碼(node)
1 const http = require('http'); 2 const url = require('url'); 3 const querystring = require('querystring'); 4 const fs = require('fs'); 5 6 /* 7 // 先後端接口: 8 用戶註冊: 9 /reg?user=xxx&pass=xxx 10 =>{error: 0, msg: '說明'} 11 12 用戶登錄: 13 /login?user=xxx&pass=xxx 14 =>{error: 0, msg: '說明'} 15 */ 16 17 // users在內存中保存用戶登錄信息 18 let users = { 19 // 'xxx': '123456', 20 // 'wyb': '654321' 21 }; 22 23 let server = http.createServer(function(req, res) { 24 // GET 25 let {pathname, query} = url.parse(req.url, true); 26 27 // POST 28 let str = ''; 29 req.on('data', function (data) { 30 str += data; 31 }); 32 33 req.on('end', function () { 34 let post = querystring.parse(str); 35 let {user, pass} = query 36 37 switch (pathname) { 38 // 註冊 39 case '/reg': 40 if (!user) { 41 res.write('{"error": 1, "msg": "user is required!"}') 42 } else if (!pass) { 43 res.write('{"error": 1, "msg": "pass is required!"}') 44 } else if (!/^\w{3,32}$/.test(user)) { 45 res.write('{"error": 1, "msg": "invalid username!"}') 46 } else if (!/^\w{6,32}$/.test(pass)) { 47 res.write('{"error": 1, "msg": "invalid password!"}') 48 } else if (/^['"|]$/.test(pass)) { 49 res.write('{"error": 1, "msg": "invalid password!"}') 50 } else if (users[user]) { 51 res.write('{"error": 1, "msg": "username already exists!"}') 52 } else { 53 users[user] = pass 54 res.write('{"error": 0, "msg": "register success!"}') 55 } 56 57 res.end() 58 break 59 // 登錄 60 case '/login': 61 if (!user) { 62 res.write('{"error": 1, "msg": "user is required!"}') 63 } else if (!pass) { 64 res.write('{"error": 1, "msg": "pass is required!"}') 65 } else if (!users[user]) { 66 res.write('{"error": 1, "msg": "no this user!"}') 67 } else if (users[user]!==pass) { 68 res.write('{"error": 1, "msg": "username or password is incorrect!"}') 69 } else { 70 res.write('{"error": 0, "msg": "login success!"}') 71 } 72 73 res.end() 74 break 75 default: 76 fs.readFile(`www${pathname}`, function (err, data) { 77 if (err) { 78 res.writeHead(404) 79 res.write("Not Found!") 80 } else { 81 res.write(data) 82 } 83 84 res.end() 85 }) 86 } 87 88 }); 89 90 }); 91 92 server.listen(8080);
4.文件上傳實例 - 用流實現