一、模塊化規(guī)范
nodejs使用的模塊化規(guī)范 叫做 common.js 規(guī)范:
每一個模塊都有獨立的作用域 代碼在各自模塊中執(zhí)行 不會造成全局污染
每一個模塊都是一個獨立的文件(module對象)
模塊可以被多次加載(module.exports 屬性) 但是僅在第一次加載時執(zhí)行一次
運行結(jié)果會被緩存 如果再次加載會從緩存中獲得結(jié)果
模塊的加載順序和代碼的書寫順序有關(guān)// exports對象是module對象的屬性,包含導(dǎo)出的信息
導(dǎo)出:module.exports ={} // module.exports.a = a || exports.a = a;默認指向以module.exports為準(zhǔn)
導(dǎo)入:count a = require(''); //只有自定義模塊需要寫路徑('./index'),導(dǎo)入對象永遠是module.exports指向的對象
二、HTTP模塊
HTTP模塊
//導(dǎo)入模塊
const http = require("http");
const https = require("https");//創(chuàng)建服務(wù)
let server = http.createServer((req, res) => {// request:解析客戶端的請求//常用屬性及方法:url(請求路徑) method(請求方法)headers(頭部)//url:請求的路徑,可以根據(jù)URL設(shè)置出路由模式,express的就是基于此設(shè)置的//methoe:請求的方式分為,post get delete put patch//headers: 請求的頭部,客戶單的cookie,數(shù)據(jù)傳輸?shù)念愋偷榷挤旁趆eader中//data事件:createServer想要獲取請求數(shù)據(jù)體需要監(jiān)聽data事件//response:相應(yīng)客戶端請求,常用屬性及方法如下://end:res.end()//setHeader(name,content),可以設(shè)置單個header屬性,可以多次設(shè)置//destory:取消返回//statusCode:設(shè)置返回的狀態(tài)碼,如200 404 400 500等//statusMessage:設(shè)置狀態(tài)碼對應(yīng)返回的信息//writeHead:可以同時設(shè)置statusCode statusMessage 和多個header屬性res.writeHead(200, { "content-type": "text/html;charset=utf-8" });let data = ""; // 返回數(shù)據(jù)// 根據(jù)不同的請求類型 設(shè)置不同的響應(yīng)頭switch (req.method) {case "GET":// data事件流 接收到數(shù)據(jù)時觸發(fā)的事件 參數(shù) chunk 數(shù)據(jù)塊,在函數(shù)內(nèi)是將數(shù)據(jù)塊拼接給datahttps.get("www.baidu.com", (res) => {res.on("data", (chunk) => (data += chunk));// end事件 在數(shù)據(jù)響應(yīng)結(jié)束時觸發(fā)res.on("end", () => {data = querystring.parse(data);// 接口路由設(shè)置 (后端數(shù)據(jù)接口)switch (req.url) {case "/users":console.log("獲取用戶信息");break;case "/addUser":// 將數(shù)據(jù)寫入數(shù)據(jù)庫data.add = true;res.end(JSON.stringify(data));break;case "/weather":weather(res);}});});break;case "POST":const options = {hostname: "",port: "443",path: "",method: "POST",headers: {"content-type": "application/json",},};https.request(options, (res) => {res.on("data", (chunk) => (data += chunk));// end事件 在數(shù)據(jù)響應(yīng)結(jié)束時觸發(fā)res.on("end", () => {data = querystring.parse(data);console.log(daat);});});req.write(JSON.stringify({ name: "", age: "" })); // 發(fā)送的請求數(shù)據(jù)req.end();break;default:}
});
//監(jiān)聽3000端口,開啟服務(wù)
server.listen(3000, () => {console.log("打開了3000端口");
});
jsonp跨域
const http = require("http");
const url = require("url");//創(chuàng)建服務(wù)
http.createServer((req, res) => {res.writeHead(200, { "content-type": "text/html;charset=utf-8" });if (req.url === "/favicon.ico") return;const urlObj = url.parse(req.url, true);res.end(`${urlObj.query.callback}(${JSON.stringify({name: "xiaoming",age: 18,})})`); // 返回一個函數(shù) fn( ${urlObj.query.callback} ) 與前端定義的 fn 名稱一致}).listen(3000, () => {console.log("打開了3000端口");});
cors頭跨域
const http = require("http");//創(chuàng)建服務(wù)
http.createServer((req, res) => {res.writeHead(200, {"content-type": "application/json;charset=utf-8","access-control-allow-origin": "*", // 跨域});res.end(JSON.stringify({name: "xiaoming",age: 18,})); // 返回一個函數(shù) fn( ${urlObj.query.callback} ) 與前端定義的 fn 名稱一致}).listen(3000, () => {console.log("打開了3000端口");});
三、URL模塊
parse模塊
const http = require("http");
const url = require("url");//創(chuàng)建服務(wù)
let server = http.createServer((req, res) => {res.writeHead(200, { "content-type": "text/html;charset=utf-8" });if (req.url === "/favicon.ico") return;console.log(url.parse(req.url, true)); // 接收第二個參數(shù),為true則轉(zhuǎn)化query對象// =Url {// protocol: null,// slashes: null,// auth: null,// host: null,// port: null,// hostname: null,// hash: null,// search: '?user=b&age=18',// query: [Object: null prototype] { user: 'b', age: '18' },// pathname: '/api',// path: '/api?user=b&age=18',// href: '/api?user=b&age=18'// }res.end();
});
//監(jiān)聽3000端口,開啟服務(wù)
server.listen(3000, () => {console.log("打開了3000端口");
});
format模塊
const url = require("url");
const urlObj= {protocol: 'https',slashes: true,auth: null,host: 'www.baidu.com:443',port: 443,hostname: 'www.baidu.com',hash: '#tag=110',search: '?user=b&age=18',query: { user: 'b', age: '18' },pathname: '/api',path: '/api?user=b&age=18',}
url.format(urlObj) => https://www.baidu.com:443/api?user=b&age=18#tag=110
resolve模塊
url.resolve('/one/two','three') => '/one/three'
url.resolve('/one/two/','three') => '/one/two/three'
url.resolve('http://www.baidu.com/a/b/c','d') => 'http://www.baidu.com/d'
新url模塊
const http = require("http");let server = http.createServer((req, res) => {res.writeHead(200, { "content-type": "text/html;charset=utf-8" });if (req.url === "/favicon.ico") return;const newUrl = new URL(req.url, "http://localhost:3000");console.log(newUrl);// URL {// href: 'http://localhost:3000/api?user=b&age=18',// origin: 'http://localhost:3000',// protocol: 'http:',// username: '',// password: '',// host: 'localhost:3000',// hostname: 'localhost',// port: '3000',// pathname: '/api',// search: '?user=b&age=18',// searchParams: URLSearchParams { 'user' => 'b', 'age' => '18' }, // 可迭代對象// hash: ''// }res.end();
});server.listen(3000, () => {console.log("打開了3000端口");
});
四、querystring模塊
const queryatring = require("querystring");const str = "name=abc&age=18&location=shanghai";
const obj = {name: "abc",age: "18",location: "shanghai",
};// 將query格式轉(zhuǎn)成對象 querystring.parse(str);
// => [Object: null prototype] {
// name: 'abc',
// age: '18',
// location: 'shanghai'
// }// 將對象轉(zhuǎn)成query格式字符串 querystring.stringify(obj);
// => "name=abc&age=18&location=shanghai"
五、爬蟲模塊
cheerio模塊
cheerio模塊為Node.js 爬蟲第三方模塊,內(nèi)置jq基本操作 // npm i cheerio
//加載數(shù)據(jù)(網(wǎng)頁),進行元素操作
let $ = cheerio.load(rawData);
六、path模塊
console.log(__dirname); // 當(dāng)前目錄 絕對路徑
console.log(__filename); // 當(dāng)前文件 絕對路徑
拼接路徑:
path.join(path):path.join('__dirname,'a','b'); //拼接當(dāng)前文件絕對路徑
獲得文件后綴:
path.extname(path)
獲得路徑名:
path.dirname(path)
七、event模塊
//導(dǎo)入模塊
const EventEmitter = require("events");const event = new EventEmitter();event.on("start", (data) => {console.log("觸發(fā)了");console.log(data);
});setTimeout(() => {event.emit("start", "開始");
}, 2000);
八、fs模塊
//導(dǎo)入模塊
count fs = require('fs');
//讀取文件
fs.readFile(url,'utf8',(err,data)=>{if (err) throw err;
})
//寫入文件
fs.writeFile(file,data[,options],callback)
//文件追加
fs.appendFile(file,data[,options],callback)
//修改文件名
fs.rename(oldpath,newpath,callback)
//讀取目錄
fs.readdir(path[,option],callback(err,files))
九、mysql模塊
連接池文件:
const mysql = require('mysql');
var pool = mysql.createPool({ // 創(chuàng)建連接池connectionLimit: 10,host: 'localhost',user: 'root',password: 'root',database: 'h5_2013'
});
module.exports = pool; //導(dǎo)出模塊文件2:
const mysql = require('pool'); //引入導(dǎo)出的配置
執(zhí)行sql語句:mysql.query('select * from users', (err, data) =>
{ // 查數(shù)據(jù)if (err) console.log(err);res.send(data); // 發(fā)送查詢到的數(shù)據(jù)
});
十、jwt模塊
token 令牌
它是一個三段式的加密字符串
xxxxxxxxxx.yyyyyyyyyyyyyyyy.zzzzzzz
第一段: 頭信息 簽證:安全信息驗證 口令 使用不可逆的哈希算法進行加密
第二段: 你需要存儲的信息 采用base64 可逆加密 截取一部分
第三段: 額外信息 使用不可逆哈希算法進行加密
瀏覽器在發(fā)送請求進行登陸時
服務(wù)器驗證完信息 信息正確 則生產(chǎn)一個 token
服務(wù)器將這個token發(fā)送給前端 前端進行存儲
如果前端請求了需要驗證登錄權(quán)限的頁面或數(shù)據(jù) 前端將token跟隨請求發(fā)回后端
后端通過解密 驗證token的有效性const jwt = require('jsonwebtoken');// 生成 token:
// jwt.sign(存儲的數(shù)據(jù),口令,參數(shù));
// 口令 是一個驗證需要的 額外字符串
// 解碼token的時候 如果口令不同就無法正確解碼// 解碼token:
// jwt.verify(token,口令,回調(diào));let userInfo = {username: 'zhangsan',age: 25,sex: 'nan',phone: 13688888888
};// 生成token
let token = jwt.sign(userInfo, 'rootbk', { expiresIn: 60 }); //expiresIn 過期時間// console.log(token);// 解碼token
jwt.verify(token, 'rootbk', (err, data) => {if (err) console.log(err.message);console.log(data);
})
十一、項目腳手架express
安裝
#你可以通過 npx (包含在 Node.js 8.2.0 及更高版本中)命令來運行 Express 應(yīng)用程序生成器。
$ npx express-generator
#對于較老的 Node 版本,請通過 npm 將 Express 應(yīng)用程序生成器安裝到全局環(huán)境中并執(zhí)行即可。
$ npm install -g express-generator
$ express name
#然后安裝所有依賴包:
$ cd myapp
$ npm install
#然后在瀏覽器中打開 http://localhost:3000/ 網(wǎng)址就可以看到這個應(yīng)用了,通過生成器創(chuàng)建的應(yīng)用一般都有如下目錄結(jié)構(gòu):- 項目名- [bin] # 存放可執(zhí)行程序- www # 開啟http服務(wù)- [public] # 存放靜態(tài)前端文件- [images]- [javascripts]- [stylesheet]- [routes] # 存放路由文件- index.js- users.js- [views] # 前端視圖模板- error.ejs- index.ejs- app.js # 主程序- package.json # 依賴信息
處理數(shù)據(jù)
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
搭建靜態(tài)web服務(wù)
const express = require('express'); // 引入第三方模塊的方式和引入內(nèi)置模塊的方式相同
const path = require('path');
const app = express(); // 創(chuàng)建一個express應(yīng)用
const conf = {port: 8888,host: '10.31.168.73'
};
// 使用express搭建一個靜態(tài)的web服務(wù)器// 靜態(tài)服務(wù)器 使用一個中間件實現(xiàn)
// 將public目錄 設(shè)置成靜態(tài)的web目錄
// public中所有內(nèi)容都可以在web服務(wù)中被訪問// app.use() 使用中間件
app.use(express.static(path.join(__dirname, 'public'))); // 靜態(tài)服務(wù)app.listen(conf.port, conf.host, () => { // 監(jiān)聽端口啟動服務(wù)console.log(`server is running at http://${conf.host}:${conf.port}`);
});
api服務(wù)
// 搭建一個api 服務(wù) 應(yīng)用程序接口
// express可以快速搭建api服務(wù)
// 接口的作用是給前端提供數(shù)據(jù)支持(CRUD)
// 前端如何發(fā)送請求
// ajax get/post
// href get
// form get/post
// jsonp getconst express = require('express');
const app = express(); // 創(chuàng)建一個express應(yīng)用
const conf = {port: 8088,host: 'localhost'
};// app.get(url,callback); 用于接受get請求
// 參數(shù)
// url[string] 請求路徑
// callback[function] 回調(diào)函數(shù)
// 回調(diào)參數(shù)
// req request
// res response
// next 函數(shù) 交出中間的控制權(quán) 將這個請求交給下一個中間件app.get('/getItem', (req, res, next) => {console.log('我收到了一個請求');// 響應(yīng)內(nèi)容// res.send() 發(fā)送數(shù)據(jù) 接受一個字符串作為參數(shù) 發(fā)送數(shù)據(jù)后自動終止請求// res.send('hahaha');// res.send({ username: 'zhangsan', age: 20 });// res.json() 發(fā)送數(shù)據(jù) 接受一個JSON 發(fā)送后自動終止請求res.json({ data:{username: 'zhangsan', age: 20},status:success });
});
app.get('/getuser', (req, res, next) => {res.json({ username: 'lisi', age: 20, success: 1 });
});
app.post('/getuser', (req, res, next) => {res.json({ username: 'xiaoming', age: 20, success: 1 });
});
app.listen(conf.port, conf.host, () => {console.log(`server is running at http://${conf.host}:${conf.port}`);
});
use中間件
const express = require('express');
const path = require('path');
const app = express();
const conf = {port: 8888,host: 'localhost'
};
// 配置靜態(tài)web服務(wù)器
app.use(express.static(path.join(__dirname, 'public')));// express 封裝的是 http 服務(wù)器
// express 接受到前端發(fā)送過來的請求 會交給 中間件 依次處理// 當(dāng)前回調(diào)函數(shù)就是我的自定義中間件
app.use((req, res, next) => {console.log('我是中間件一號');// 如果在中間中沒有使用 send 或 json 結(jié)束請求// 這個請求會被認為沒有完成 進程將被掛起// next 調(diào)用next可以將中間件的控制權(quán)交出 // 將這個請求傳遞給下一個中間件next();// res.send('hahah');
});
app.use((req, res, next) => {console.log('我是中間件二號');next();
});
app.listen(conf.port, conf.host, () => {console.log(`server is running at http://${conf.host}:${conf.port}`);
});
request模塊-實現(xiàn)跨源請求(代理)
const express = require('express');
const request = require('request');
const querystring = require('querystring');
const app = express();
let requestUrl = 'http://api.k780.com/?';
let props = {app: 'weather.future',cityNm: '杭州',appkey: '38926',sign: 'f8b4121c2d581be2623569b24f798dee',format: 'json'
}
requestUrl += querystring.stringify(props);
app.get('/api', (req, res, next) => {request(requestUrl, (err, response, body) => {if (err) console.log(err);res.send(body);});
});
app.listen(8877, 'localhost', () => {console.log('start');
});