欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報(bào)激活碼778899分享:vim node.js學(xué)習(xí)

柚子快報(bào)激活碼778899分享:vim node.js學(xué)習(xí)

http://yzkb.51969.com/

node.js學(xué)習(xí)實(shí)操及筆記

溫故node.js,node.js學(xué)習(xí)實(shí)操過程及筆記~

node.js學(xué)習(xí)視頻node.js官網(wǎng)node.js中文網(wǎng)實(shí)操筆記githubcsdn筆記

為什么學(xué)node.js

可以讓別人訪問我們編寫的網(wǎng)頁為后續(xù)的框架學(xué)習(xí)打下基礎(chǔ),三大框架vue react angular離不開node.js

node.js是什么

官網(wǎng):node.js是一個(gè)開源的、跨平臺(tái)的運(yùn)行JavaScript的運(yùn)行環(huán)境。通俗理解: 一款應(yīng)用程序,一款軟件,可以運(yùn)行JavaScript

node.js作用

開發(fā)服務(wù)器應(yīng)用開發(fā)工具類應(yīng)用開發(fā)桌面類應(yīng)用

node.js安裝

node.js官網(wǎng)node.js中文網(wǎng)全部版本安裝包淘寶鏡像

點(diǎn)擊安裝,傻瓜式安裝。

PS:推薦使用nvm方式安裝node.js,這樣可實(shí)現(xiàn)自由切換版本好。

因?yàn)橛械睦享?xiàng)目node.js可能是12版本的,新項(xiàng)目又是18或者20版本。具體安裝自行查閱,目前這邊已經(jīng)安裝,忘記哪個(gè)博主寫的較好就不推薦了。

檢測(cè)安裝是否成功,輸入以下命令到命令行,出來版本號(hào)代表安裝成功

node -v

若安裝失敗,考慮大可能為環(huán)境變量配置問題影響

node.js初體驗(yàn)

當(dāng)前目錄新建hello.js

console.log("hello node.js!");

切換到當(dāng)前目錄,終端打開執(zhí)行代碼,看到 hello node.js 注意:運(yùn)行命令為node + 文件路徑 =》hello.js是相對(duì)文件路徑,這里省略了./hello.js

node hello.js

node.js注意事項(xiàng)

node.js不能使用BOM、DOM的API,可以使用console和定時(shí)器APInode.js中頂級(jí)對(duì)象為global,也可以用globalThis訪問頂級(jí)對(duì)象

// BOM不可用

console.log(window);

console.log(history);

console.log(navigator);

console.log(location)

//DOM不可用

console.log(document);

//global可用 globalthis可用

console.log(global)

//定時(shí)器可用

setTimeout(()=>{

console.log('hello~')

})

Buffer緩沖器

Buffer概念

概念

Buffer是一個(gè)類似數(shù)組的對(duì)象,用于固定長(zhǎng)度的字節(jié)序列Buffer本質(zhì)是一段內(nèi)存空間,專門用來處理二進(jìn)制數(shù)據(jù)

特點(diǎn)

Buffer大小固定且無法調(diào)整Buffer性能較好,可以直接對(duì)計(jì)算機(jī)內(nèi)存進(jìn)行操作每個(gè)元素的大小為1字節(jié) 3.創(chuàng)建BufferallocallocUnsafefrom

node.js內(nèi)置模塊Buffer,不需引入,理解為全局變量

//1.alloc

let buf = Buffer.alloc(10);

console.log(buf);

console.log('-------')

// 2.allocUnsafe;

let buf_2 = Buffer.allocUnsafe(10000);

console.log(buf_2);

console.log('-------')

//3.from

//打印出ASCII碼字符代碼表的值

let buf_3 = Buffer.from('hello');

console.log(buf_3);

console.log('-------');

//打印出二進(jìn)制的值

let buf_4 = Buffer.from([105, 108, 111, 118, 101, 121, 111, 117]);

console.log(buf_4);

console.log('-------');

Buffer操作以及注意點(diǎn)

字符串轉(zhuǎn)換(默認(rèn)采用utf-8方式轉(zhuǎn)換)

let buf_4 = Buffer.from([105, 108, 111, 118, 101, 121, 111, 117]);

console.log(buf_4);

console.log('-------');

//1-字符串轉(zhuǎn)換 默認(rèn)采用utf-8方式轉(zhuǎn)換

const str = buf_4.toString();

console.log(str);

元素的讀取以及修改

[]進(jìn)行單個(gè)元素的讀取以及修改大于255的值,溢出,舍棄高位,留下后8位二進(jìn)制utf-8編碼方式,1個(gè)漢字對(duì)應(yīng)3個(gè)字節(jié)

let buf_5 = Buffer.from('hello');

//1-[]括號(hào)方式進(jìn)行單個(gè)元素的查看 二進(jìn)制轉(zhuǎn)換的查看

console.log(buf_5[0]);//打印出十進(jìn)制

console.log(buf_5[0].toString(2));//實(shí)際上是01101000

//2-單個(gè)元素的修改

// 直接修改

buf_5[0] = 95;

//查看修改后的字符串的值

console.log(buf_5.toString());//輸出_ello

//溢出

buf_5[0] = 361;//舍棄高位超出8位的數(shù)字 0001 0110 1001

console.log(buf_5);//69 0001被舍棄,留下0110 1001

//中文

let buf_6 = Buffer.from('你好');//utf-8編碼方式 1個(gè)漢字對(duì)應(yīng)3個(gè)中文

console.log(buf_6);//輸出

計(jì)算機(jī)基礎(chǔ)

計(jì)算機(jī)基本組成

CPU 中央處理器,運(yùn)算與控制的核心。工作時(shí)會(huì)產(chǎn)生大量熱量,一般連接一個(gè)散熱器進(jìn)行散熱。內(nèi)存 讀寫速度較快,斷電丟失數(shù)據(jù)硬盤 讀寫速度較慢,斷電不丟失數(shù)據(jù)主板 CPU 內(nèi)存 硬盤 通過主板連接在一起顯卡 負(fù)責(zé)處理視頻信號(hào),有信息需要在顯示器呈現(xiàn),就會(huì)將信號(hào)傳遞到顯卡,顯卡處理完畢再將信號(hào)傳遞給顯示器,顯示器最終顯示

程序運(yùn)行基本流程

安裝好上面CPU等,還需安裝操作系統(tǒng)方可運(yùn)行。 操作系統(tǒng):

操作系統(tǒng)也是一種應(yīng)用程序,用來管理和調(diào)度硬件資源。將操作系統(tǒng)安裝到硬盤,電腦即可開機(jī)運(yùn)行。 常見操作系統(tǒng)

WindowsLinuxMacOs 總結(jié):程序一般保存到硬盤中,軟件安裝的過程就是將程序?qū)懭胗脖P的過程。程序在運(yùn)行時(shí)會(huì)加載進(jìn)入內(nèi)存,然后由CPU讀取并執(zhí)行程序

進(jìn)程與線程

進(jìn)程包含一個(gè)或多個(gè)線程。進(jìn)程>線程

進(jìn)程

通俗理解為進(jìn)行中的程序進(jìn)程是程序的一次執(zhí)行過程

線程

線程是一個(gè)進(jìn)程中執(zhí)行的一個(gè)執(zhí)行流一個(gè)線程是屬于某個(gè)進(jìn)程的

fs模塊

全稱:file system 文件系統(tǒng)。fs模塊可以實(shí)現(xiàn)與硬盤的交互。 例如文件的創(chuàng)建、刪除、重命名、移動(dòng),還有文件內(nèi)容的寫入、讀取,以及文件夾的操作。

寫入文件

語法: fs.writeFile(file,data[,option],callback)

同步與異步

異步:情況比如做飯,按下了煮飯鍵就去炒菜。同步:類似排隊(duì),一個(gè)完成接著一個(gè)。對(duì)效率要求高的基本都是用異步API。

異步寫入語法: fs.writeFile(file,data[,option],callback)同步寫入語法: fs.writeFileSync(file,data[,option])

/** 需求

* 新建一個(gè)文件夾為座右銘.txt(info.txt)

* 寫入內(nèi)容為 三人行,必有我?guī)熝伞?/p>

*/

const fs = require("fs");

//寫入文件 異步寫入

fs.writeFile('./info.txt', '三人行,必有我?guī)熝桑?, (err) => {

if (err) {

console.error("寫入錯(cuò)誤:")

console.error(err);

return;

}

console.log("寫入成功!")

})

//寫入文件

// 同步寫入

fs.writeFileSync('./infoSync.txt', '測(cè)試同步寫入');

// 流式寫入

const ws = fs.createWriteStream('./writeStream.txt');

ws.write('床前明月光\r\n');

ws.write('疑是地上霜\r\n');

ws.write('舉頭望明月\r\n');

ws.write('低頭思故鄉(xiāng)\r\n');

//關(guān)閉

ws.end();

文件追加寫入

文件追加多用于程序日志,不斷往文件追加內(nèi)容

方法說明fs.appendFile(file,data[,option],callback)異步追加fs.appendFileSync(file,data[,option])同步追加fs.writeFile(file,data[,option],callback)添加標(biāo)識(shí)異步追加option為{flag:'a'}

// 文件追加寫入

const fs = require('fs');

// 異步追加

fs.appendFile('./info.txt', '\r\n哈哈哈追加內(nèi)容下!', err => {

if (err) {

console.error(err);

return;

}

console.log('追加內(nèi)容成功!')

})

//同步追加內(nèi)容

fs.appendFileSync('./infoSync.txt', '\r\n同步追加內(nèi)容看看!');

// 異步追加內(nèi)容

fs.writeFile('./info.txt', '\r\n哈哈哈writeFile追加!', {flag: 'a'}, err => {

if (err) {

console.error('追加錯(cuò)誤:');

console.error(err);

return;

}

console.log('追加成功!')

})

流式寫入

程序打開一個(gè)文件需要消耗資源,流式寫入可以減少文件的次數(shù)。 流式寫入方式適用于大文件寫入或者頻繁寫入的場(chǎng)景,writeFile適用于寫入頻率較低的場(chǎng)景。

流式讀?。p少連接次數(shù),連接后不斷開)語法:fs.createWriteStream(path[,option])

參數(shù)說明:

path 文件路徑options選項(xiàng)配置

返回值 Object

代碼示例:

//寫入文件

// 同步寫入

fs.writeFileSync('./infoSync.txt', '測(cè)試同步寫入');

// 流式寫入

const ws = fs.createWriteStream('./writeStream.txt');

ws.write('床前明月光\r\n');

ws.write('疑是地上霜\r\n');

ws.write('舉頭望明月\r\n');

ws.write('低頭思故鄉(xiāng)\r\n');

//關(guān)閉

ws.end();

文件寫入應(yīng)用場(chǎng)景

當(dāng)需要持久化保存數(shù)據(jù)的時(shí)候,應(yīng)該想到文件寫入

下載文件安裝軟件保存程序日志,如Git編輯器保存文件視頻錄制

文件讀取

程序從文件中取出其中的數(shù)據(jù)。

方法說明fs.readFile(file,data[,option],callback)異步讀取fs.readFileSync(file,data[,option])同步讀取fs.createReadStream(file,data[,option],callback)流式讀取

代碼示例:

// 文件讀取

const fs = require('fs');

// 異步讀取

fs.readFile('./info.txt', (err, data) => {

if (err) {

console.error('讀取錯(cuò)誤:');

console.error(err);

return;

}

console.log('讀取成功!')

console.log(data.toString());

})

console.log('-----------------');

// 同步讀取

const readDataSync = fs.readFileSync('./infoSync.txt');

console.log('同步讀取:')

console.log(readDataSync.toString());

console.log('-----------------');

// 流式讀取

// 創(chuàng)建視頻流對(duì)象

const rs = fs.createReadStream('./writeStream.txt');

// 綁定data事件 chunk 塊

rs.on('data', chunk => {

console.log('---------!!----------');

// 字符串類文件讀取可以,要是讀取的的mp4文件,用toString輸出將會(huì)亂碼,直接console.log(chunk)即可

console.log(chunk.toString());

console.log('---------!!----------');

})

// end可選事件

rs.on('end', () => {

console.log('流式讀取完成!');

})

讀取文件應(yīng)用場(chǎng)景

電腦開機(jī)程序運(yùn)行編輯器打開文件查看圖片播放視頻播放音樂Git查看日志上傳文件查看聊天記錄

fs練習(xí)_復(fù)制文件

代碼示例:

/** fs練習(xí)_復(fù)制文件

* 將writeSteam.txt內(nèi)容復(fù)制,新建writeStreamCopy.txt

*/

// 思路

// 1- readFile讀取內(nèi)容

// 2- writeFile新建文件

// 1、同步讀取寫入

const fs = require('fs');

// 讀取

const readDataCopy = fs.readFileSync('./writeStream.txt');

// 寫入

fs.writeFileSync('./writeStreamCopy.txt', readDataCopy);

console.log('測(cè)試內(nèi)存:');

// PS:注釋下面流式讀取 得出內(nèi)存

console.log(process.memoryUsage());// 28119040字節(jié) ?1024 約等于 281366.25kb ?1024 約等于 274.78Mb

console.log('------------------------');

// 2、流式讀取寫入

//創(chuàng)建讀取流對(duì)象

const rsCopy = fs.createReadStream('./writeStream.txt');

// 創(chuàng)建寫入流對(duì)象

const wsCopy = fs.createWriteStream('./writeStreamCopyStream.txt');

// 1-綁定data事件

rsCopy.on('data', chunk => {

wsCopy.write(chunk);

})

// 2-on('data')方法復(fù)制或直接使用 管道 直接復(fù)制

// rsCopy.pipe(wsCopy);

// rsCopy.on('end', () => {

// console.log('測(cè)試內(nèi)存:');

// // PS:注釋上面直接讀取 得出內(nèi)存

// console.log(process.memoryUsage());// 28434432字節(jié) ?1024 約等于 27768kb ?1024 約等于 27.117Mb

// console.log('------------------------');

// })

文件重命名和移動(dòng)

異步移動(dòng)語法 fs.rename(oldPath,newPath,callback)同步移動(dòng)語法fs.renameSync(oldPath,newPath)

參數(shù)說明

oldPath:文件當(dāng)前路徑newPath:文件新的路徑callback:操作后的回調(diào)

代碼示例:

// fs重命名

const fs = require('fs');

//重命名:將文件1重命名為infoRename.txt

fs.rename('./info.txt', './infoRename.txt', err => {

if (err) {

console.error('重命名失敗:');

console.error(err);

return;

}

console.log('重命名成功!');

})

// 確保目標(biāo)目錄存在

if (!fs.existsSync('./file')) {

fs.mkdirSync('./file');

}

// 移動(dòng):將重命名后的文件1移動(dòng)到file文件夾,命名為info.txt

fs.rename('./infoSync.txt', './file/infoMove.txt', err => {

if (err) {

console.error('移動(dòng)失?。?);

console.error(err);

return;

}

console.log('移動(dòng)成功!');

})

文件刪除

異步刪除語法 fs.unlink(path,callback) 同步刪除語法fs.unlinkSync(path) 異步刪除fs.rm(path,callback) ps:node.js14.4版本以上才可用 同步刪除fs.rmSync(path) ps:node.js14.4版本以上才可用

參數(shù)說明:

path:文件路徑callback:操作后的回調(diào)

代碼示例:

// 文件刪除

const fs = require('fs');

//unlink刪除

fs.unlink('./info.txt', (err) => {

if (err) {

console.error(err);

return;

}

console.log('刪除成功!');

})

fs.unlinkSync('./infoSync.txt');

// rm刪除 node.js14.4版本以上

fs.rm('./writeStream.txt', (err) => {

if (err) {

console.error(err);

return;

}

console.log('刪除成功2!');

})

fs.rmSync('./writeStreamCopyStream.txt');

文件夾操作

創(chuàng)建文件夾mkdir/mkdirSync讀取文件夾readdir/readdirSync刪除文件夾rmdir/rmdirSync

方法說明mkdir/mkdirSync創(chuàng)建文件夾readdir/readdirSync讀取文件夾rmdir/rmdirSync刪除文件夾

PS:判斷文件夾是否存在

同步判斷語法 fs.existsSync(path[,option])

參數(shù)說明:

path:文件路徑

創(chuàng)建文件夾

異步創(chuàng)建語法:fs.mkdir(path,callback)同步創(chuàng)建語法:fs.mkdirSync(path)

代碼示例:

// 文件夾操作_創(chuàng)建文件夾

const fs = require('fs');

// 創(chuàng)建文件

//先判斷是否存在

if (!fs.existsSync('./newFile')) {

fs.mkdir('./newFile', err => {

if (err) {

console.log('創(chuàng)建失?。?);

console.error(err);

return;

}

console.log('創(chuàng)建成功');

})

}

//先判斷是否存在

if (!fs.existsSync('./a/b/c', {recursive: true})) {

// 遞歸創(chuàng)建文件夾

fs.mkdir('./a/b/c', {recursive: true}, err => {

if (err) {

console.log('創(chuàng)建失敗2:');

console.error(err);

return;

}

console.log('創(chuàng)建成功2');

})

}

//先判斷是否存在

if (!fs.existsSync('./test2/d/e', {recursive: true})) {

fs.mkdirSync('./test2/d/e', {recursive: true});

}

讀取文件夾

異步讀取語法:fs.readdir(path,callback)同步讀取語法:fs.readdirSync(path)

參數(shù)說明:

path:路徑

代碼示例

// 文件夾操作——讀取文件夾

const fs = require('fs');

// 創(chuàng)建文件

fs.readdir('./newFile', (err, data) => {

if (err) {

console.log('讀取文件夾失?。?);

console.error(err);

return;

}

console.log('讀取文件夾成功');

console.log(data);

})

// 讀取文件夾

fs.readdir('./file', (err, data) => {

if (err) {

console.log('讀取文件夾失敗2:');

console.error(err);

return;

}

console.log('讀取文件夾成功2');

console.log(data);

})

const readfileData = fs.readdirSync('./test2');

console.log('同步讀取文件夾');

console.log(readfileData);

刪除文件夾

不推薦使用rmdir

異步刪除語法:fs.rmdir(path,callback)同步刪除語法:fs.rmdirSync(path)

推薦使用rm:

異步刪除語法:fs.rm(path,callback)同步刪除語法:fs.rmSync(path)

參數(shù)說明:

path:路徑

代碼示例:

// 刪除文件夾

const fs = require('fs');

//遞歸刪除 不推薦使用rmdir 推薦使用rm

fs.rmdir('./a',{ recursive: true }, (err) => {

if(err){

console.log('刪除文件夾出錯(cuò)');

console.error(err);

return;

}

console.log('刪除文件夾成功!');

})

fs.rmdirSync('./test2', {recursive: true});

//rm刪除

fs.rm('./newFile',{ recursive: true }, (err) => {

if(err){

console.log('刪除文件夾出錯(cuò)2:');

console.error(err);

return;

}

console.log('刪除文件夾成功2!');

})

fs.rmSync('./test', {recursive: true});

查看資源狀態(tài)

異步查看語法:fs.stat(path[,option],callback)同步查看語法: fs.statSync(path[,option])

參數(shù)說明:

path 文件路徑options 選項(xiàng)配置(可選)callback 操作后的回調(diào)

示例代碼:fs_stat.js

/** 查看資源狀態(tài)

* fs.stat()

*/

const fs = require('fs');

// 異步獲取狀態(tài)

fs.stat('./info.txt', (err, data) => {

if(err){

console.log('查看資源失?。?)

console.log(err);

return;

}

console.log('異步查看資源成功!詳細(xì)信息如下:')

console.log(data);

//判斷是否是一個(gè)文件方法 isFile()

console.log('是文件嗎?')

console.log(data.isFile());

// 判斷是否是一個(gè)文件夾方法 isDirectory()

console.log("是文件夾嗎?")

console.log(data.isDirectory());

})

// 同步獲取狀態(tài)

const data = fs.statSync('./info.txt');

console.log('同步查看資源成功!詳細(xì)信息如下:')

console.log(data);

結(jié)果值對(duì)象結(jié)構(gòu):

size 文件體積birthtime 創(chuàng)建時(shí)間mtime 最后修改時(shí)間isFile 檢測(cè)是否為文件isDirectory 檢測(cè)是否為文件夾…

路徑補(bǔ)充說明

路徑分為相對(duì)路徑和絕對(duì)路徑兩種寫法

相對(duì)路徑

比如在當(dāng)前根目錄的info.txt

相對(duì)路徑表達(dá)為./info.txt

相對(duì)路徑常遇到的bug與解決

相對(duì)路徑參照的是命名行的工作目錄!

Bug:

比如在 代碼利用相對(duì)路徑創(chuàng)建文件./info.txt:

在當(dāng)前命令運(yùn)行node fs_writeFile.js就在當(dāng)前文件夾生成info.txt在nodejs上層運(yùn)行node ./nodejs/fs_writeFile.js就會(huì)在nodejs同級(jí)生成info.txt

結(jié)論:

相對(duì)路徑的參照物 是在運(yùn)行命令行的當(dāng)前目錄

解決方法

利用絕對(duì)路徑:使用全局變量__dirname進(jìn)行拼接:保存的是所在文件的所在目錄的絕對(duì)路徑

代碼示例:

//使用絕對(duì)路徑:__dirname拼接方式

//利用絕對(duì)路徑:使用全局變量`__dirname`進(jìn)行拼接:保存的是所在文件的所在目錄的`絕對(duì)路徑`

fs.writeFileSync(__dirname+'/index.html','寫入內(nèi)容哈哈哈哈')

絕對(duì)路徑

常會(huì)遇到權(quán)限的問題

比如在D盤下的info.txt

絕對(duì)路徑表達(dá)為D:/info.txtlinux操作系統(tǒng)下用的較多/開頭,比如/info.txt

fs練習(xí)_批量重命名

優(yōu)化如下:

視頻用的是split會(huì)拆分,這里我用的是正則表達(dá)式視頻用的是相對(duì)路徑,這里我拼接了__dirname使用了絕對(duì)路徑

示例代碼:

/** 批量重命名

* 需求:將code文件夾里面的文件

* 名稱為前面為1-9的命名為01-09

*/

// 思路

// 1-讀取readdirSync里面的文件名稱 fs.readdirSync(path,callback)

// 2-重命名renameSync fs.renameSync(path,callback)

const fs = require('fs');

const files = fs.readdirSync(__dirname + '/code');

console.log('名稱為:');

console.log(files);

// 讀取文件修改

files.forEach(file => {

const oldPath = __dirname + '/code/' + file;

// 利用正則表達(dá)式_前面是一位數(shù)的補(bǔ)0

const newFileName = file.replace(/^(\d)_(.+)$/i, "0$1_$2");

const newPath = __dirname + '/code/' + newFileName;

//重命名

fs.renameSync(oldPath, newPath);

})

path模塊

path模塊提供了操作路徑的功能。

常用API如下:

API說明path.resolve拼接規(guī)范的絕對(duì)路徑 常用path.sep獲得操作系統(tǒng)的路徑分隔符path.parse解析路徑并返回對(duì)象path.basename獲得路徑基礎(chǔ)名稱path.dirname獲得路徑目錄名path.extname獲得路徑擴(kuò)展名

resolve(重點(diǎn)掌握)

代碼示例:

// path模塊

const fs = require('fs');

const path = require('path');

// 寫入文件

// 建議絕對(duì)路徑 +拼接+ 相對(duì)路徑 寫法 path.resolve(絕對(duì)路徑+相對(duì)路徑)

fs.writeFileSync(path.resolve(__dirname, './test.txt'), 'peace and love');

// 不建議這樣寫 最好不要 絕對(duì)路徑+絕對(duì)路徑寫法 /path為絕對(duì)路徑

// 這樣寫的意思是 /path的絕對(duì)路徑 +拼接+ ./test.txt

// fs.writeFileSync(path.resolve(__dirname, '/path', './test.txt'), 'peace and love');

運(yùn)行命令

node ./path/path.js

sep

sep分隔符 :不同操作系統(tǒng)的分隔符不同,獲取不同操作系統(tǒng)下的分隔符

操作系統(tǒng)分隔符windows\linux/macos/

代碼示例:

const path = require('path');

// sep分隔符 :不同操作系統(tǒng)的分隔符不同,獲取不同操作系統(tǒng)下的分隔符

console.log(path.sep); //windows:\ linux:/ macos:/

path

解析路徑返回對(duì)象=》語法: path.parse(path)

參數(shù)說明:

path:文件解析路徑

代碼示例:

// parse 解析路徑并返回對(duì)象

// 查看當(dāng)前文件路徑

console.log(__filename);

//定義路徑

let str = '/Users/lhm/Documents/nodejs/path/path.js'

// 解析路徑

console.log(path.parse(str));

basename

獲得文件名=》語法: path.basename(path)

參數(shù)說明:

path:文件解析路徑

代碼示例:

// basename 獲取路徑名稱

// 查看當(dāng)前文件路徑

console.log(__filename);

//定義路徑

let str = '/Users/lhm/Documents/nodejs/path/path.js'

// 獲取的文件名

console.log(path.basename(str)); //path.js

dirname

獲得文件夾的目錄名=》語法: path.dirname(path)

參數(shù)說明:

path:文件解析路徑

代碼示例:

// dirname 獲取文件目錄名

// 查看當(dāng)前文件路徑

console.log(__filename);

//定義路徑

let str = '/Users/lhm/Documents/nodejs/path/path.js'

// 獲取文件目錄名

console.log(path.dirname(str)); // /Users/lhm/Documents/nodejs/path

extname

獲得文件擴(kuò)展名(即為后綴名)=》語法: path.extname(path)

參數(shù)說明:

path:文件解析路徑

代碼示例:

// extname 獲取文件擴(kuò)展名即為后綴名

// 查看當(dāng)前文件路徑

console.log(__filename);

//定義路徑

let str = '/Users/lhm/Documents/nodejs/path/path.js'

// 獲取文件擴(kuò)展名

console.log(path.extname(str)); // .js

HTTP協(xié)議

初識(shí)

全稱 Hypertext Transfer Protocol 超文本傳輸協(xié)議 互聯(lián)網(wǎng)應(yīng)用最廣泛的協(xié)議之一協(xié)議:雙方必須共同遵從的一組約定瀏覽器 輸入 url 給服務(wù)器發(fā)送 請(qǐng)求報(bào)文, 服務(wù)器 給 瀏覽器 發(fā)送響應(yīng)報(bào)文 進(jìn)行響應(yīng)

HTTP報(bào)文

安裝軟件fiddler 查看報(bào)文內(nèi)容,自行下載摸索。

請(qǐng)求報(bào)文結(jié)構(gòu)

請(qǐng)求行 GET https://www.baidu.com請(qǐng)求頭請(qǐng)求體

請(qǐng)求行

如 GET https://www.baidu.com/ HTTP/1.1

構(gòu)成

請(qǐng)求方法URLHTTP版本號(hào)

請(qǐng)求方法

常見方法如下:

方法作用GET主要用于獲取數(shù)據(jù)POST主要用于新增數(shù)據(jù)PUT/PATCH主要用于更新數(shù)據(jù)DELETE主要用于刪除數(shù)據(jù)HEAD/OPTIONS/CONNECT/TRACE使用相對(duì)較少

URL

全程 Uniform Resource Locator 統(tǒng)一資源定位符 比如:https://search.jd/com:443/search?keyword=oneplus&psort=12

協(xié)議名 https主機(jī)名 search.jd.com端口號(hào) 443路徑 /search查詢字符串 ?keyword=oneplus&psort=12

HTTP版本號(hào) 常見版本號(hào):

版本號(hào)發(fā)布時(shí)間1.01996年1.11999年22015年32018年

請(qǐng)求頭

很多鍵值對(duì)組成,主要是記錄瀏覽器很多相關(guān)的信息,記錄與瀏覽器交互的行為。

點(diǎn)擊跳轉(zhuǎn)MDN查看請(qǐng)求頭

請(qǐng)求體

用一個(gè)場(chǎng)景理解它。比如登錄場(chǎng)景 ,發(fā)送post請(qǐng)求傳過去的數(shù)據(jù):username=111&password=asaj11212。這些即為請(qǐng)求體。

響應(yīng)報(bào)文

響應(yīng)行響應(yīng)頭響應(yīng)體

響應(yīng)行

HTTP版本號(hào)響應(yīng)狀態(tài)碼響應(yīng)狀態(tài)的描述

響應(yīng)狀態(tài)碼

狀態(tài)碼含義200請(qǐng)求成功403禁止請(qǐng)求404找不到資源500服務(wù)器內(nèi)部錯(cuò)誤

響應(yīng)狀態(tài)的描述

響應(yīng)狀態(tài)的描述通常與狀態(tài)碼相關(guān)

狀態(tài)碼狀態(tài)描述200OK403Forbidden404Not Found500Internal Server Error

點(diǎn)擊查看更多狀態(tài)碼

響應(yīng)頭

跟請(qǐng)求頭一樣為鍵值對(duì)的形式,記錄與服務(wù)器相關(guān)的一些內(nèi)容。

點(diǎn)擊查看更多響應(yīng)頭

響應(yīng)體

響應(yīng)體即響應(yīng)的內(nèi)容

常見的響應(yīng)體格式有:

HTMLCSSJavaScript圖片視頻JSON

網(wǎng)絡(luò)基礎(chǔ)概念

IP

IP也稱為[IP地址],本身是一個(gè)數(shù)字標(biāo)識(shí)。例如 192.168.1.3。 通俗理解IP地址主要用來尋找網(wǎng)絡(luò)設(shè)備,本身是32Bit的二進(jìn)制數(shù)字。

作用:

IP用來標(biāo)識(shí)網(wǎng)絡(luò)中的設(shè)備,實(shí)現(xiàn)設(shè)備間的通信

IP的分類

類型說明本地回環(huán)IP地址127.0.0.1 ~ 127.255.255.255局域網(wǎng)IP(私網(wǎng)IP)192.168.0.0 ~ 192.168.255.255172.16.0.0~172.31.255.25510.0.0.0 ~ 10.255.255.255廣域網(wǎng)(公網(wǎng)IP)除上述之外

端口

端口:應(yīng)用程序的數(shù)字標(biāo)識(shí)。一臺(tái)現(xiàn)代計(jì)算機(jī)有65536個(gè)端口(0~65535)。一個(gè)應(yīng)用程序可以使用一個(gè)或多個(gè)端口。 通俗理解: 趕集的攤位的 編號(hào) 好比 計(jì)算機(jī)理解的端口

作用:

實(shí)現(xiàn)不同主機(jī)應(yīng)用程序之間的通信

http模塊

創(chuàng)建http服務(wù)端

代碼示例:./http/createServer.js

// 創(chuàng)建服務(wù)

// 1.導(dǎo)入http模塊

const http = require('http');

// 2.創(chuàng)建服務(wù)對(duì)象

const server = http.createServer((request, response) => {

//設(shè)置響應(yīng)內(nèi)容

response.end('Hello World! Hello node.js Server!');

});

// 3.監(jiān)聽端口,啟動(dòng)服務(wù)

server.listen(9000, () => {

console.log("Server started on port 9000...");

console.log('http://localhost:9000/');

})

注意事項(xiàng)

命令行ctrl + c停止服務(wù)當(dāng)服務(wù)啟動(dòng)后,更新代碼必須重啟服務(wù)才能生效響應(yīng)內(nèi)容中文亂碼的解決方法

response.setHeader('content-type','text/html;charset=utf-8')

端口號(hào)被占用

關(guān)閉當(dāng)前正在運(yùn)行監(jiān)聽端口的服務(wù)使用較多修改其他端口號(hào)

HTTP協(xié)議默認(rèn)端口號(hào)是80。HTTP服務(wù)開發(fā)常用端口有3000,8080,8090,9000等

獲取http請(qǐng)求報(bào)文

想要獲取請(qǐng)求的數(shù)據(jù),需要通過request對(duì)象

含義語法重點(diǎn)掌握請(qǐng)求方法request.method*請(qǐng)求http協(xié)議版本request.httpVersion請(qǐng)求路徑request.url*請(qǐng)求頭request.headers*請(qǐng)求體request.on(‘data’,function(chunk){})request.on(‘end’,function(){});url請(qǐng)求路徑const url = require(‘url’); url.parse(request.url).pathname;*url查詢字符串const url = require(‘url’); url.parse(request.url,true).query;

注意事項(xiàng):

request.ur;只能獲取路徑以及查詢的字符串,無法獲取URL中的域名以及協(xié)議的內(nèi)容request.headers將請(qǐng)求信息轉(zhuǎn)化為一個(gè)對(duì)象,并將屬性名都轉(zhuǎn)換成了【小寫】關(guān)于路徑:如果訪問網(wǎng)站的時(shí)候,只寫了IP地址或者是域名信息,此時(shí)請(qǐng)求的路徑為【/】關(guān)于favicon.ico:這個(gè)請(qǐng)求是屬于瀏覽器自動(dòng)發(fā)送的請(qǐng)求

請(qǐng)求頭

代碼示例:./http/request_header.js

ps:瀏覽器打開form.html輸入提交進(jìn)行測(cè)試 ps:當(dāng)端口被占用,關(guān)閉其它運(yùn)行9000端口的終端,或者修改運(yùn)行端口號(hào)。

// 請(qǐng)求報(bào)文之請(qǐng)求頭

//引入http模塊

const http = require("http");

//創(chuàng)建服務(wù)對(duì)象

const server = http.createServer((request, response) => {

// 1-----請(qǐng)求頭

//請(qǐng)求方法

console.log('請(qǐng)求方法');

console.log(request.method);

// 請(qǐng)求http版本

console.log('請(qǐng)求http版本');

console.log(request.httpVersion);

// 請(qǐng)求頭

console.log('請(qǐng)求url');

console.log(request.headers.host);

// 請(qǐng)求路徑

console.log('請(qǐng)求路徑');

console.log(request.url);

})

//啟動(dòng)服務(wù)

server.listen(9000, () => {

console.log('server listening on port 9000,');

console.log("http://localhost:9000/");

})

請(qǐng)求體

代碼示例:./http/request_content.js

ps:瀏覽器打開form.html輸入提交進(jìn)行測(cè)試 ps:當(dāng)端口被占用,關(guān)閉其它運(yùn)行9000端口的終端,或者修改運(yùn)行端口號(hào)。

// 請(qǐng)求報(bào)文之請(qǐng)求體

//引入http模塊

const http = require("http");

//創(chuàng)建服務(wù)對(duì)象

const server = http.createServer((request, response) => {

// ----請(qǐng)求體

// 定義請(qǐng)求體內(nèi)容

let body = '';

request.on('data', (chunk) => {

body += chunk;

})

request.on('end', () => {

console.log('請(qǐng)求體內(nèi)容:')

console.log(body);

console.log('--------end--------------')

response.end('hello world!');

})

})

//啟動(dòng)服務(wù)

server.listen(9000, () => {

console.log('server listening on port 9000,');

console.log("http://localhost:9000/");

})

請(qǐng)求路徑與查詢關(guān)鍵字

方式1:通過內(nèi)置url解析

請(qǐng)求路徑語法:url.parse(request.url).pathname)查詢字符串語法:url.parse(request.url,true).query

注意事項(xiàng): 2. 運(yùn)行:當(dāng)端口被占用,關(guān)閉其它運(yùn)行9000端口的終端,或者修改運(yùn)行端口號(hào)。 2. 在瀏覽器輸入進(jìn)行測(cè)試觀察終端打印日志:點(diǎn)擊跳轉(zhuǎn)瀏覽器進(jìn)行測(cè)試

代碼示例:./http/request_url.js

// 請(qǐng)求報(bào)文之url

//引入http模塊

const http = require("http");

const url = require("url");

//創(chuàng)建服務(wù)對(duì)象

const server = http.createServer((request, response) => {

// ----url

console.log('請(qǐng)求路徑:')

console.log(url.parse(request.url).pathname);

console.log('查詢字符串:')

console.log(url.parse(request.url,true).query);

console.log(url.parse(request.url,true).query.username);

console.log(url.parse(request.url,true).query.password);

console.log('---------------');

response.end('hello world!');

})

//啟動(dòng)服務(wù)

server.listen(9000, () => {

console.log('server listening on port 9000,');

console.log("http://localhost:9000/");

})

方式2:通過new URL解析

語法:new URL(input[,base]) 點(diǎn)擊了解更多new URL英文 點(diǎn)擊了解更多new URL中文

注意事項(xiàng):

運(yùn)行:當(dāng)端口被占用,關(guān)閉其它運(yùn)行9000端口的終端,或者修改運(yùn)行端口號(hào)。在瀏覽器輸入進(jìn)行測(cè)試觀察終端打印日志:點(diǎn)擊跳轉(zhuǎn)瀏覽器進(jìn)行測(cè)試

代碼示例:./http/request_newURL.js

// 請(qǐng)求報(bào)文之url

//引入http模塊

const http = require("http");

//創(chuàng)建服務(wù)對(duì)象

const server = http.createServer((request, response) => {

// 2- 通過new URL方式獲取

let url = new URL(request.url, 'http://localhost:9000');

console.log(url);

console.log('請(qǐng)求路徑:')

console.log(url.pathname);

console.log('查詢字符串');

console.log(url.searchParams.get('username'));

console.log('------------------')

})

//啟動(dòng)服務(wù)

server.listen(9000, () => {

console.log('server listening on port 9000,');

console.log("http://localhost:9000/");

})

http請(qǐng)求練習(xí)

注意事項(xiàng):

運(yùn)行:當(dāng)端口被占用,關(guān)閉其它運(yùn)行9000端口的終端,或者修改運(yùn)行端口號(hào)。在瀏覽器輸入進(jìn)行測(cè)試觀察終端打印日志:

登錄頁面:點(diǎn)擊跳轉(zhuǎn)瀏覽器進(jìn)行測(cè)試注冊(cè)頁面:點(diǎn)擊跳轉(zhuǎn)瀏覽器進(jìn)行測(cè)試不存在:點(diǎn)擊跳轉(zhuǎn)瀏覽器進(jìn)行測(cè)試

/** http練習(xí)

* 需求

* 請(qǐng)求類型 get 地址/login 返回 “登錄頁面” 四字

* 請(qǐng)求類型 get 地址/reg 返回 “注冊(cè)頁面” 四字

*/

const http = require('http');

const server = http.createServer((req, res) => {

if (req.method === 'GET') {

let url = new URL(req.url, 'http://127.0.0.1:9000');

//設(shè)置中文防止亂碼

res.setHeader('Content-Type', 'text/html; charset=UTF-8');

if (url.pathname === '/login') {

res.end('登錄頁面');

} else if (url.pathname === '/reg') {

res.end('注冊(cè)頁面');

} else {

res.end('您當(dāng)前訪問頁面不存在!');

}

} else {

res.end('您當(dāng)前訪問頁面不存在!');

}

});

server.listen(9000, () => {

console.log('Server started on port 9000,');

console.log('http://localhost:9000,');

})

設(shè)置http響應(yīng)報(bào)文

作用語法設(shè)置響應(yīng)狀態(tài)碼response.statusCode設(shè)置響應(yīng)狀態(tài)描述response.statusMessage(用的非常少)設(shè)置響應(yīng)頭信息response.setHeader(‘頭名’,‘頭值’)設(shè)置響應(yīng)體response.write(‘xx’);response.end(‘xx’);

注意事項(xiàng):

運(yùn)行:當(dāng)端口被占用,關(guān)閉其它運(yùn)行9000端口的終端,或者修改運(yùn)行端口號(hào)。在瀏覽器輸入此url進(jìn)行請(qǐng)求,打開瀏覽器——右鍵檢查——查看網(wǎng)絡(luò):

點(diǎn)擊跳轉(zhuǎn)瀏覽器進(jìn)行測(cè)試

代碼示例:

// 設(shè)置響應(yīng)頭

//引入http模塊

const http = require("http");

//創(chuàng)建服務(wù)對(duì)象

const server = http.createServer((request, response) => {

// 設(shè)置響應(yīng)

//響應(yīng)狀態(tài)碼

response.statusCode = 200;

//設(shè)置響應(yīng)狀態(tài)信息

response.statusMessage = 'iloveyou';

// 設(shè)置響應(yīng)頭

// 設(shè)置編碼格式 防止中文亂碼

response.setHeader('content-type', 'text/html; charset=utf-8');

// 自定義響應(yīng)頭

response.setHeader('myHeaders', 'Authorization');

//響應(yīng)體 write可有多個(gè)

response.write('哈哈哈哈 響應(yīng)體');

response.write('哈哈哈哈2 響應(yīng)體');

// 響應(yīng)體 end 只有一個(gè)

response.end('bye!!')

});

//啟動(dòng)服務(wù)

server.listen(9000, () => {

console.log('server listening on port 9000,');

console.log("http://localhost:9000/");

})

http響應(yīng)練習(xí)

注意事項(xiàng):

運(yùn)行:當(dāng)端口被占用,關(guān)閉其它運(yùn)行9000端口的終端,或者修改運(yùn)行端口號(hào)。在瀏覽器輸入此url進(jìn)行請(qǐng)求查看效果:

點(diǎn)擊跳轉(zhuǎn)瀏覽器進(jìn)行測(cè)試

代碼示例:res.pratice.html + res_pratice.js

/** http響應(yīng)練習(xí)

* 需求

* 搭建http服務(wù),響應(yīng)一個(gè)4行3列的表格

* 并且要求表格有 隔行換色效果,且點(diǎn)擊單元格能高亮顯示

*/

const fs = require('fs');

const http = require('http');

const server = http.createServer((req, res) => {

res.setHeader('content-type', 'text/html;charset=UTF-8');

const html = fs.readFileSync(__dirname+'/res_pratice.html');

res.end(html);

});

server.listen(9000, () => {

console.log('Server started on port 9000,');

console.log('http://localhost:9000/');

})

網(wǎng)頁資源加載的全部過程

1-先加載html 2-再根據(jù)html內(nèi)容加載css、圖片資源、js等 3-favicon.icon請(qǐng)求:瀏覽器默認(rèn)行為:默認(rèn)請(qǐng)求網(wǎng)站圖標(biāo)favicon.icon 4-ws請(qǐng)求:插件行為,使得網(wǎng)頁實(shí)現(xiàn)自動(dòng)刷新功能

實(shí)現(xiàn)網(wǎng)頁引入外部資源

接回之前的響應(yīng)練習(xí),現(xiàn)在需求是將css js分離開,單獨(dú)引入資源

代碼示例: res_pratice.js => 讀取res_practice.html res_pratice.css pratice_click.js

/** http響應(yīng)練習(xí)

* 需求

* 搭建http服務(wù),響應(yīng)一個(gè)4行3列的表格

* 并且要求表格有 隔行換色效果,且點(diǎn)擊單元格能高亮顯示

*/

const fs = require('fs');

const http = require('http');

const server = http.createServer((req, res) => {

//按路徑區(qū)分 請(qǐng)求資源 進(jìn)行 響應(yīng)。不要都響應(yīng)此html

const {pathname} = new URL(req.url, 'http://127.0.0.1')

if (pathname === '/') {

//注意:此響應(yīng)頭得在html里,否則可能會(huì)沒效果

res.setHeader('content-type', 'text/html;charset=UTF-8');

const html = fs.readFileSync(__dirname + '/res_pratice.html');

res.end(html);

} else if (pathname === '/res_pratice.css') {

const css = fs.readFileSync(__dirname + '/res_pratice.css');

res.end(css);

} else if (pathname === '/pratice_click.js') {

const js = fs.readFileSync(__dirname + '/pratice_click.js');

res.end(js);

} else {

res.end('

404 Not Found!

');

}

});

server.listen(9000, () => {

console.log('Server started on port 9000,');

console.log('http://localhost:9000/');

})

靜態(tài)資源與動(dòng)態(tài)資源

靜態(tài)資源:內(nèi)容長(zhǎng)時(shí)間不發(fā)生改變的資源,例如圖片,視頻,css文件,js文件,HTML文件,字體文件等動(dòng)態(tài)資源:內(nèi)容經(jīng)常更新的資源,例如百度首頁,網(wǎng)易首頁,京東搜索列表頁面等。

搭建靜態(tài)資源服務(wù)

對(duì)響應(yīng)式練習(xí)的優(yōu)化處理

利用__dirname+pathname進(jìn)行拼接,無需多次請(qǐng)求

代碼示例:

/** http響應(yīng)練習(xí)

* 需求

* 搭建http服務(wù),響應(yīng)一個(gè)4行3列的表格

* 并且要求表格有 隔行換色效果,且點(diǎn)擊單元格能高亮顯示

*/

const fs = require('fs');

const http = require('http');

const server = http.createServer((req, res) => {

//按路徑區(qū)分 請(qǐng)求資源 進(jìn)行 響應(yīng)。不要都響應(yīng)此html

// const {pathname} = new URL(req.url, 'http://127.0.0.1')

// if (pathname === '/') {

// //注意:此響應(yīng)頭得在html里,否則可能會(huì)沒效果

// res.setHeader('content-type', 'text/html;charset=UTF-8');

// const html = fs.readFileSync(__dirname + '/res_pratice.html');

// res.end(html);

// } else if (pathname === '/res_pratice.css') {

// const css = fs.readFileSync(__dirname + '/res_pratice.css');

// res.end(css);

// } else if (pathname === '/pratice_click.js') {

// const js = fs.readFileSync(__dirname + '/pratice_click.js');

// res.end(js);

// } else {

// res.end('

404 Not Found!

');

// }

// 優(yōu)化

const {pathname} = new URL(req.url, 'http://127.0.0.1')

const filename = pathname === '/' ? __dirname + '/res_pratice.html' : __dirname + pathname;

fs.readFile(filename, 'utf8', (err, data) => {

if (err) {

res.end('

404 Not Found!

');

console.error(err);

return;

}

res.end(data);

})

});

server.listen(9000, () => {

console.log('Server started on port 9000,');

console.log('http://localhost:9000/');

})

網(wǎng)頁URL之絕對(duì)路徑

絕對(duì)路徑可靠性強(qiáng),而且相對(duì)性容易理解,在項(xiàng)目中運(yùn)用較多

形式特點(diǎn)http://www.baidu.com直接向目標(biāo)資源發(fā)送請(qǐng)求,容易理解。網(wǎng)站的外鏈會(huì)用到此形式。//www.baidu.com與頁面URL的協(xié)議拼接形成完整URL再發(fā)送請(qǐng)求。大型網(wǎng)站用的比較多/web與頁面URL的協(xié)議、主機(jī)名、端口拼接形成完整URL再發(fā)送請(qǐng)求。中小型網(wǎng)站

網(wǎng)頁URL之相對(duì)路徑

相對(duì)路徑在發(fā)送請(qǐng)求時(shí),需要與當(dāng)前頁面URL路徑進(jìn)行計(jì)算,得到完整URL后,再發(fā)送請(qǐng)求,學(xué)習(xí)階段用的較多。 例如當(dāng)前網(wǎng)頁url為:http://www.atguigu.com/course/h5.html

形式最終的URL./css/app.csshttp://www.atguigu.com/course/css/app.cssjs/app/jshttp://www.atguigu.com/course/js/app.js…/img/logo.pnghttp://www.atguigu.com/img/logo.png…/mp4/show.mp4http://www.atguigu.com/mp4/show.mp4

網(wǎng)頁中使用URL的場(chǎng)景小結(jié)

包括但不限于以下場(chǎng)景:

a標(biāo)簽hreflink標(biāo)簽hrefscript標(biāo)簽srcimg標(biāo)簽srcvideo audio 標(biāo)簽 srcform中的actionAJAX請(qǐng)求中的URL

設(shè)置mime類型

媒體類型 通常稱為Multipurpose Internet Mail Extension 或 MIME 類型)是一種標(biāo)準(zhǔn),用來表示文檔、文件或字節(jié)流的性質(zhì)和格式。

mime 類型結(jié)構(gòu): [type]/[subType]

例如: text/html images/jpeg image/png application/json

HTTP服務(wù)可以設(shè)置響應(yīng)頭Content-Type來表明響應(yīng)體的MIME類型,瀏覽器會(huì)根據(jù)該類型決定如何處理資源 下面是常見的文件對(duì)應(yīng)的mime類型

html: `text/html`

css:`text/css`

js:`text/javascript`

png:`images/png`

jpg:`images/jpeg`

gif:`images/gif`

mp4:`video/mp4`

mp3:`audio/mpeg`

json:`application/json`

對(duì)于未知的資源類型,可選擇application/actet-stream類型,瀏覽器在遇到該類型響應(yīng)時(shí),會(huì)對(duì)該響應(yīng)體類型進(jìn)行獨(dú)立存儲(chǔ),也就是我們常見的下載效果

代碼示例:./http/mime.js

// 設(shè)置mime

const http = require('http');

const path = require('path');

const server = http.createServer((req, res) => {

// 優(yōu)化

const {pathname} = new URL(req.url, 'http://127.0.0.1');

const filepath = pathname === '/' ? __dirname + '/res_pratice.html' : __dirname + pathname;

// 得到后綴名

const extname = path.extname(filepath).slice(1);

// 根據(jù)請(qǐng)求文件后綴名,設(shè)置相應(yīng)的mime

let mimes = {

html: 'text/html',

css: "text/css",

js: 'text/javascript',

png: 'images/png',

jpg: 'images/jpeg',

gif: 'images/gif',

mp4: 'video/mp4',

mp3: 'audio/mp3',

json: 'application/json'

}

// 獲取對(duì)應(yīng)類型

const type = mimes[extname];

// 判斷

if (type) {

//解決亂碼問題

if(extname==='html'){

res.setHeader('Content-Type', type+';charset=utf-8');

}else{

res.setHeader('Content-Type', type);

}

} else {

res.setHeader('Content-Type', 'application/actet-stream');

}

fs.readFile(filepath, 'utf8', (err, data) => {

if (err) {

res.end('

404 Not Found!

');

console.error(err);

return;

}

res.end(data);

})

});

server.listen(9000, () => {

console.log('server started');

console.log('http://localhost:9000/');

})

解決亂碼問題

html添加字符集charset:utf-8即可.響應(yīng)頭的字符集優(yōu)先于html的meta設(shè)置的字符集

代碼示例:如上:./http/mime.js

完善錯(cuò)誤處理

點(diǎn)擊node.js中文網(wǎng)查看錯(cuò)誤代碼具體含義

代碼處理示例:error.js

// 完善錯(cuò)誤處理

const http = require('http');

const fs = require('fs');

const server = http.createServer((req, res) => {

// 優(yōu)化

const {pathname} = new URL(req.url, 'http://127.0.0.1');

const filepath = pathname === '/' ? __dirname + '/res_pratice.html' : __dirname + pathname;

fs.readFile(filepath, 'utf8', (err, data) => {

if (err) {

console.error(err);

switch (err.code) {

case 'ENOENT':

res.statusCode = 404;

res.end('

404 Not Found!

');

case 'EPERM':

res.statusCode = 403;

res.end('

403 Forbidden!

');

default:

res.statusCode = 500;

res.end('

Internal Server Error

');

}

return;

}

res.end(data);

})

});

server.listen(9000, () => {

console.log('server started');

console.log('http://localhost:9000/');

})

GET和POST使用場(chǎng)景

GET請(qǐng)求場(chǎng)景:

在地址欄直接輸入url訪問點(diǎn)擊a鏈接link標(biāo)簽引入cssscript標(biāo)簽引入jsvideo與audio引入多媒體img標(biāo)簽引入圖片form標(biāo)簽中的method為get

POST請(qǐng)求中的請(qǐng)求

form標(biāo)簽中的method為postAJAX中的post請(qǐng)求

GET和POST請(qǐng)求區(qū)別

GET和POST是HTTP協(xié)議請(qǐng)求中的兩種方式,主要有以下區(qū)別:

作用:GET主要是用來獲取數(shù)據(jù),POST主要是用來提交數(shù)據(jù)參數(shù)位置:GET主要用來獲取數(shù)據(jù),POST主要用來提交數(shù)據(jù)安全性:POST請(qǐng)求相對(duì)GET安全一些,因?yàn)樵跒g覽器中會(huì)暴露在地址欄GET請(qǐng)求大小有限制,一般為2k,而POST請(qǐng)求則沒有大小限制

模塊化

什么是模塊化

將一個(gè)復(fù)雜的程序文件依據(jù)一定規(guī)則(規(guī)范)拆分成多個(gè)文件的過程稱之為模塊化 其中拆分出的每個(gè)文件就是一個(gè)模塊。模塊內(nèi)部的數(shù)據(jù)是私有的,不過模塊可以暴露內(nèi)部數(shù)據(jù)以使其它模塊使用

模塊化項(xiàng)目: 編碼時(shí)按照模塊一個(gè)個(gè)編碼的,整個(gè)項(xiàng)目就是一個(gè)模塊化的項(xiàng)目

模塊化好處:

防止命名沖突高復(fù)用性高維護(hù)性

模塊化初體驗(yàn)

Commonjs規(guī)范

代碼示例:me.js

// 聲明函數(shù)

function tiemo(){

console.log('timemo')

}

module.exports = tiemo;

代碼示例:index.js

//引入模塊

const tiemo = require('./me');

// 調(diào)用

tiemo();

運(yùn)行:

./module/index.js 是相對(duì)于當(dāng)前打開終端的目錄路徑,根據(jù)自己路徑找到index.js

node ./module/index.js

模塊暴露數(shù)據(jù)

方式1:module.exports = value方式2:module.exports = {value1,value2}方式3:export.name = value

?注意:不要直接exports = value ? 錯(cuò)誤寫法

代碼示例: me.js

// 聲明函數(shù)

function tiemo() {

console.log('timemo')

}

function niejiao() {

console.log('niejiao');

}

// 暴露數(shù)據(jù)

// module.exports = tiemo;

// 暴露數(shù)據(jù)2

module.exports = {

tiemo,

niejiao

}

// 暴露數(shù)據(jù)3

// exports.niejiao = niejiao;

// exports.tiemo = tiemo;

// 注意:不能使用 exports=value的形式暴露數(shù)據(jù)

// 因?yàn)槿缦孪嗟?/p>

// exports = module.exports = {tiemo: tiemo}

// exports.tiemo = tiemo;

代碼示例:index.js 調(diào)用

//引入模塊

const me = require('./me');

// 調(diào)用

me.tiemo();

me.niejiao();

導(dǎo)入模塊

在模塊中使用require傳入文件路徑即可使用文件

const test = require('./me.js');

require使用的一些注意事項(xiàng)

對(duì)于自己創(chuàng)建的模塊,導(dǎo)入時(shí)路徑建議寫相對(duì)路徑,不能省略./和../js和json文件導(dǎo)入時(shí)可以不用寫后綴,c/c++編寫的node擴(kuò)展文件也可不寫后綴,但一般用不到如果導(dǎo)入其他類型的文件,會(huì)以js文件進(jìn)行處理如果導(dǎo)入路徑為文件夾,首先會(huì)檢測(cè)package.json文件中main屬性對(duì)應(yīng)的文件,如果main屬性不存在,或者package.json不存在,則會(huì)檢測(cè)文件夾下的index.js和index.json.如果還是沒找到,就會(huì)報(bào)錯(cuò)導(dǎo)入node.js內(nèi)置模塊時(shí),直接require模塊的名字即可,無需加./和../

Node.js實(shí)現(xiàn)了CommonJS模塊化規(guī)范

導(dǎo)入模塊的基本流程

介紹require導(dǎo)入自定義模塊的基本流程

將相對(duì)路徑轉(zhuǎn)為絕對(duì)路徑,定位目標(biāo)文件緩存檢測(cè)讀取目標(biāo)文件代碼包裹為一個(gè)函數(shù)并執(zhí)行(自執(zhí)行函數(shù))。通過arguments.callee.toString()查看自執(zhí)行函數(shù)緩存模塊的值返回module.exports值

CommonJS規(guī)范

module.exports exports 以及require 這些都是CommonJS模塊化規(guī)范中的內(nèi)容Node.js是實(shí)現(xiàn)了CommonJS模塊化規(guī)范,二者關(guān)系有點(diǎn)像JavaScript與ECMAScript

包管理工具

包管理工具就像哆啦A夢(mèng)

介紹

【包】英文單詞 package 代表了一組特定功能的源碼集合

包管理工具 管理【包】的應(yīng)用軟件,可以對(duì)【包】進(jìn)行下載安裝,更新,刪除,上傳等操作

常用的包管理工具

npmyarncnpm

npm安裝與介紹

node.js在安裝時(shí)會(huì)自動(dòng)安裝npm,若你已經(jīng)安裝了node.js,可以直接使用npm

通過 npm -v查看版本號(hào)測(cè)試。顯示版本號(hào)即為成功,反之失敗

npm初始化包

我在此新建了npm文件夾,并切換終端目錄到npm,使用cd npm切換到npm文件夾也可。

npm init (根據(jù)問題回答~使用默認(rèn)就回車)

?注意:

中文和英文大寫命名不允許,默認(rèn)是文件夾的名稱,所以文件夾也不能用中文和大寫version版本號(hào)要求x.x.x形式定義,x必須是數(shù)字,默認(rèn)值1.0.0ISC證書與MIT證書功能上是相同的,關(guān)于開源證書擴(kuò)展閱讀:點(diǎn)擊查看package.json可以手動(dòng)創(chuàng)建以及修改使用npm init -y 或者npm init --yes 極速創(chuàng)建package.json

搜索包

方式2種

命令行 【npm s/search 關(guān)鍵字】網(wǎng)站搜索 網(wǎng)址是:https://www.npmjs.com

關(guān)于如何精準(zhǔn)找到需要的包 這個(gè)事情需要在實(shí)踐中不斷積累,通過看文章,看項(xiàng)目去學(xué)習(xí)積累

下載依賴包

npm install 簡(jiǎn)寫 npm i

require導(dǎo)入npm包基本流程

在當(dāng)前文件夾的node_modules中尋找同名的文件夾在上級(jí)目錄下的node_modules中尋找同名的文件夾,直至找到磁盤根目錄

生產(chǎn)環(huán)境與開發(fā)環(huán)境

開發(fā)環(huán)境是程序員 專門用來寫代碼 的環(huán)境,一般是指程序員的電腦,開發(fā)環(huán)境的項(xiàng)目一般只能是程序員自己訪問生產(chǎn)環(huán)境是項(xiàng)目代碼正式運(yùn)行的環(huán)境,一般是指正式的服務(wù)器電腦,生產(chǎn)環(huán)境的項(xiàng)目一般每個(gè)客戶都可以訪問

生產(chǎn)依賴與開發(fā)依賴

我們可以在安裝時(shí)設(shè)置區(qū)分依賴的類型,目前分為兩類

類型命令補(bǔ)充生產(chǎn)依賴npm i -S uniqnpm i --save uniq-S等效于–save -S是默認(rèn)選項(xiàng)包信息保存在package.json中的dependencies屬性開發(fā)依賴npm i -D lessnpm i --save-dev less-D等效于–save-dev -S是默認(rèn)選項(xiàng)包信息保存在package.json中的devDependencies屬性

比如蛋炒飯需要 大米 油 蔥 雞蛋 鍋 煤氣 鏟子 其中 鍋 煤氣 鏟子 屬于開發(fā)依賴,只在制作階段使用 而大米 有 蔥 雞蛋屬于生產(chǎn)依賴 在制作與最終食用都會(huì)用 所以開發(fā)依賴是只在開發(fā)階段使用的依賴包,而生產(chǎn)依賴是開發(fā)階段和最終上線運(yùn)行階段都用到的依賴包

npm全局安裝

npm i -g nodemon

全局安裝完成之后就可以在命令行的任何位置運(yùn)行nodemon命令 該命令作用是自動(dòng)重啟node應(yīng)用程序?!拘薷奈募a后不需關(guān)閉終端,重新運(yùn)行,會(huì)自動(dòng)監(jiān)測(cè)編譯】 使用nodemon運(yùn)行即可

nodemon ./fs/fs_writeFile.js

與此同時(shí)修改./fs/fs_writeFile.js文件會(huì)自動(dòng)編譯,不需要關(guān)閉重新運(yùn)行

?注意:

全局安裝命令不受工作目錄位置影響可以通過npm root -g 查看全局安裝包位置只有全局類的工具才適合全局安裝

環(huán)境變量path

命令行輸入命令會(huì)在當(dāng)前目錄尋找.exe或者.cmd后綴可執(zhí)行文件執(zhí)行,找到執(zhí)行,找不到則報(bào)錯(cuò)。 比如輸入QQ 會(huì)在當(dāng)前文件夾尋找 QQ.exe或者QQ.cmd的可執(zhí)行文件。找不到就去環(huán)境變量中找,所以路徑需配置在環(huán)境變量中。

安裝所有依賴

npm i / npm install

npm i

npm安裝指定版本的包

語法:npm i <包名@版本包> 示例:

npm i jquery@1.11.2

npm刪除包

npm remove / npm rnpm uninstall / npm uni 全局刪除示例:

npm remove -g modemon

局部刪除示例:

npm remove uniq

npm uninstall juery

npm命令配置別名

通過package.json中配置script

npm start 是項(xiàng)目中常用命令,用來啟動(dòng)命令??刹患?runnpm run 有自動(dòng)向上級(jí)目錄查找的特性,跟require函數(shù)一樣默認(rèn)對(duì)于陌生項(xiàng)目,我們可以先通過查看scripts屬性來參考項(xiàng)目的一些操作??煽吹皆趺催\(yùn)行項(xiàng)目、打包項(xiàng)目等

示例如:(配置了start啟動(dòng)命令)

{

"name": "test",

"version": "1.0.0",

"description": "學(xué)習(xí)npm",

"main": "index.js",

"scripts": {

"test": "echo \"Error: no test specified\" && exit 1",

"start": "node ./test.js"

},

"author": "",

"license": "ISC",

"dependencies": {

"uniq": "^1.0.1"

}

}

2.運(yùn)行

npm run start

cnpm

介紹

cnpm淘寶搭建的npmjs.com的完整鏡像,也稱為【淘寶鏡像】,網(wǎng)址cnpm服務(wù)部署在國(guó)內(nèi)阿里云服務(wù)器上,可以提高的下載速度官網(wǎng)也提供了一個(gè)全局工具包c(diǎn)npm,操作命令與npm大體相同

安裝

npm install -g cnpm --registry=https://registry.npmmirror.com

操作命令

基本跟npm相同

功能命令初始化cnpm init安裝包c(diǎn)npm i uniqcnpm i -S uniqcnpm i -D uniqcnpm i -g nodemon安裝項(xiàng)目依賴cnpm i刪除cnpm r uniqcnpm uni uniq

配置淘寶鏡像

用npm可直接下載淘寶鏡像,配置方式有兩種

直接配置工具配置

直接配置

npm config set registry https://registry.npmmirror.com/

工具配置

安裝nrm

npm i -g nrm

修改鏡像

nrm use taobao

檢查是否配置成功

npm config list

PS: 檢查registry地址是否為https://reggistry/npmmirror.com/ 如果是則表明成功

補(bǔ)充說明:

建議使用第二種方式進(jìn)行鏡像配置,因?yàn)楹罄m(xù)修改起來會(huì)比較方便雖然cnpm可以提高速度,但是npm也可以通過淘寶鏡像進(jìn)行加速,所以npm使用率還是高于cnpm

yarn

介紹

yarn是Facebook在2016年推出的JavaScript推出的包管理工具 官網(wǎng)網(wǎng)址

特點(diǎn)

速度超快:yam 緩存了每個(gè)下載過的包,所以再次使用時(shí)無需重復(fù)下載。 同時(shí)利用并行下載以最大化資源利用率,因此安裝速度更快超級(jí)安全:在執(zhí)行代碼之前,yarn 會(huì)通過算法校驗(yàn)每個(gè)安裝包的完整性超級(jí)可靠:使用詳細(xì)、簡(jiǎn)潔的鎖文件格式和明確的安裝算法,yarn 能夠保證在不同系統(tǒng)上無差異的工作

安裝

npm i -g yarn

yarn常用命令

功能命令初始化yarn init / yarn init -y安裝包yarn add uniq 生產(chǎn)依賴yarn add less --dev 開發(fā)依賴yarn global add nodemon 全局安裝安裝項(xiàng)目依賴yarn刪除yarn remove uniq 刪除項(xiàng)目依賴包yarn global remove nodemon 全局刪除包運(yùn)行命令別名yarn <別名>

npm 和 yarn 選擇

大家可以根據(jù)不同場(chǎng)景進(jìn)行選擇

個(gè)人項(xiàng)目,根據(jù)個(gè)人喜好選擇公司項(xiàng)目:根據(jù)項(xiàng)目代碼選擇,可以選擇通過鎖文件判斷項(xiàng)目的包管理工具

npm 鎖文件是 package-lock.jsonyarn 鎖文件是 yarn.lock

包管理工具不要混用,切記,切記,切記

npm發(fā)布一個(gè)包

創(chuàng)建與發(fā)布

將自己開發(fā)的工具包發(fā)布到npm服務(wù)上,方便自己和其它開發(fā)者進(jìn)行使用,操作步驟如下:

創(chuàng)建文件夾,并創(chuàng)建文件main中index.js入口文件,在文件中聲明刪除,使用module.exports暴露

代碼示例:

function add(a, b) {

return a + b;

}

module.exports = {

add

}

npm初始化工具包npm init,package.json填寫包的信息(包名必須唯一)注冊(cè)賬號(hào)激活賬號(hào)(一定要激活賬號(hào))修改為官方鏡像

之前使用了別的鏡像,比如淘寶鏡像加速,不切回官方鏡像很可能會(huì)上傳失敗.

通過nrm方式切回官方鏡像: 沒安裝的先安裝: npm i -g nrm

切回官方鏡像: nrm use npm

登錄npm,按照要求登錄

npm login

提交發(fā)布包

npm publish

更新包

更新包中代碼測(cè)試代碼是否可用修改package.json中版本號(hào)發(fā)布更新

npm publish

刪除包

npm unpublish

不成功加上--force強(qiáng)制刪除

npm unpublish --force

刪除包需要一定條件,查看條件

你是包作者發(fā)布小于24小時(shí)大于24小時(shí)后,沒有其他包依賴,并且每周小于300下載量,并且只有一個(gè)維護(hù)者

包管理工具擴(kuò)展介紹

很多語言都有包管理工具。除了編程語言,操作系統(tǒng)層面也存在包管理工具。

語言包管理工具PHPcomposerPythonpipJavamavenGogo modJavaScriptnpm/yarn/cnpm/otherRubyrubyGems

操作系統(tǒng)也存在包管理工具,不過這個(gè)包指的是軟件包:

操作系統(tǒng)包管理工具網(wǎng)址Centoscomposerhttps://package.debian.org/stabel/Ubuntuapthttps://package.ubuntu.com /MacOShomeviewhttps://brew.sh /Windowschocolateyhttps://chocolatey.org

nvm介紹與使用

介紹

nvm 全稱 Node Version Manager 顧名思義用來管理node版本工具。方便切換不用版本的Node.js。一般項(xiàng)目中,新舊項(xiàng)目要求的node版本不同,建議使用nvm安裝node.js,方便切換

下載安裝

安裝太久,不知道哪個(gè)博文好使了,可以去網(wǎng)上尋找細(xì)致教程

windows的github下載地址選擇 nvm-setup.exe 下載即可

常用命令

命令說明nvm use available顯示可下載的Node.js版本nvm list顯示已安裝的版本nvm install 18.12.1安裝18.12.1版本的Node.jsnvm install latest安裝最新版本的Node.jsnvm uninstall 18.12.1刪除18.12.1版本的Node.jsnvm use 18.12.1切換18.12.1的Node.js

express

express介紹

官網(wǎng)介紹:expresss是一個(gè)基于Node.js平臺(tái)的極簡(jiǎn)、靈活的WEB應(yīng)用開發(fā)框架。官網(wǎng)網(wǎng)址.簡(jiǎn)單來說,express是一個(gè)封裝好的工具包,封裝了很多功能,便于我們開發(fā)WEB應(yīng)用。(HTTP服務(wù)) http模塊幫助我們搭建http服務(wù),給瀏覽器做出相應(yīng)服務(wù)端的功能,直接使用還是不太方面,于是我們借助express框架.

express路由

路由確定了應(yīng)用程序如何響應(yīng)客戶對(duì)特定端點(diǎn)的請(qǐng)求。

express依舊兼容之前的http的獲取請(qǐng)求及其響應(yīng)方法!

路由基本使用

一個(gè)路由有請(qǐng)求方法、路徑和回調(diào)函數(shù)組成 express中提供了一系列方法,可以很方便的使用路由 使用格式如下:

app.(path,callback)

PS:代碼中1-4方法使用,知識(shí)點(diǎn)

代碼示例:startlearn.js

// 初認(rèn)識(shí)express

// 引入模塊

const express = require('express');

// 創(chuàng)建應(yīng)用對(duì)象

const app = express();

const port = 3000;

// 1-創(chuàng)建路由 get方法

app.get('/home', (req, res) => {

res.end('hello world');

})

// 2-創(chuàng)建路由 get方法

app.post('/login', (req, res) => {

res.end('hello login');

})

//3- 無論get或post方法

app.all('/test', (req, res) => {

res.end('no matter methods');

})

//4-上面匹配不上的路由規(guī)則

app.all('*', (req, res) => {

res.end('404 No Found');

})

//監(jiān)聽端口 啟動(dòng)服務(wù)

app.listen(port, () => {

console.log('Express server started');

console.log('http://localhost:9000/');

})

獲取請(qǐng)求報(bào)文參數(shù)

說明原生http獲取express框架獲取獲取請(qǐng)求路徑pathconst url = require(‘url’); url.parse(request.url).pathname; / new URL(req.url,‘http://localhost:9000’).pathnamereq.path獲取請(qǐng)求參數(shù)const url = require(‘url’); url.parse(request.url,true).query;req.query獲取ipreq.connection.remoteAddressreq.ip獲取請(qǐng)求頭req.headers[‘host’]req.get(‘host’)

獲取路由參數(shù)

語法eg=》路徑/:id 通過req.params.id獲取路由參數(shù)

代碼示例:

const express = require('express');

const app = express();

//通配符 通過http://localhost:3000/login/1212121訪問即可知

app.get('/login/:id', (req, res) => {

// 獲取id

console.log(req.params.id);

res.end('login success!');

})

app.get('/', (req, res) => {

res.end('hello');

})

//監(jiān)聽端口 啟動(dòng)服務(wù)

app.listen(3000, () => {

console.log('Express server started');

console.log('http://localhost:3000');

})

路由參數(shù)練習(xí)

運(yùn)行后點(diǎn)擊測(cè)試 代碼示例如下:singer.json + params_pratice.js

/** 需求

* 通過路由id返回歌手名稱及其它名稱

*/

const express = require('express');

const app = express();

const fs = require('fs');

// 讀取歌手假數(shù)據(jù)json文件

const singersData = fs.readFileSync(__dirname + '/singers.json').toString();

app.get('/singer/:id', (req, res) => {

const {id} = req.params;

const matchData = JSON.parse(singersData).singers.find(item => item.id === Number(id));

res.setHeader('content-type', 'text/html; charset=utf-8');

if (matchData) {

res.end(`名稱:${matchData.singer_name},其它名稱:${matchData.other_name}`);

} else {

res.end('No Such a Singer');

}

})

app.listen(3000, () => {

console.log('Express server started');

console.log('http://localhost:3000');

})

一般響應(yīng)設(shè)置

設(shè)置響應(yīng)狀態(tài)碼:res.status(200)設(shè)置請(qǐng)求頭:res.set(‘a(chǎn)sas’,‘a(chǎn)aa’)設(shè)置響應(yīng)內(nèi)容: res.send(‘你好’)連貫操作:res.status(200).set(‘hahaha~’, ‘hhh’).send(‘你好 express’);

代碼示例如下:

const express = require('express');

const app = express();

app.get('/', (req, res) => {

// //原生響應(yīng)也兼容

// res.statusCode = 200;

// res.statusMessage = 'asasa';

// res.setHeader('hahha', 'hhh');

// res.write('hello world!');

// res.end('res content');

// express設(shè)置狀態(tài)碼

// res.status(200);

// // express設(shè)置請(qǐng)求頭

// res.setset('hahaha~', 'hhh');

// // express響應(yīng)內(nèi)容 做了封裝 中文不亂碼

// res.send('你好');

// 連貫操作

res.status(200).set('hahaha~', 'hhh').send('你好 express');

})

app.listen(3000, () => {

console.log('server started on port 3000');

console.log('http://localhost:3000');

});

其它響應(yīng)設(shè)置

設(shè)置重定向:res.redirect(‘http://www.baidu.com’)下載響應(yīng):res.download(‘路徑’)響應(yīng)json: res.json({內(nèi)容)響應(yīng)文件內(nèi)容:res.sendFile(__dirname+‘/home.html’)

// 其它響應(yīng)

app.get('/other', (req, res) => {

//1-設(shè)置重定向

// res.redirect('http://www.baidu.com');

// 2-下載響應(yīng)

// res.download(__dirname + '/singers.json');

// 3-響應(yīng)json

// res.json({

// "singer_name": "林俊杰",

// "other_name": " JJ Lin",

// "id": 2

// });

//4-響應(yīng)文件內(nèi)容

res.sendFile(__dirname + '/test.html');

})

中間件

中間件介紹

本質(zhì)是一個(gè)回調(diào)函數(shù)可以像回調(diào)喊出一樣訪問 請(qǐng)求對(duì)象,響應(yīng)對(duì)象

中間件作用

中間件作用就是使用函數(shù)封裝公共操作,簡(jiǎn)化代碼

中間件類型

全局中間件路由中間件

全局中間價(jià)

每一個(gè)請(qǐng)求到達(dá)服務(wù)端之后都會(huì)執(zhí)行全局中間件代碼

代碼示例:middleware.js

// 認(rèn)識(shí)中間件

/** 需求

* 追加日志記錄,寫入log.txt文件

*/

const express = require('express');

const app = express();

const fs = require('fs');

const path = require('path');

// 全局中間件

// 定義

function recordMiddleWare(req, res, next) {

// 判斷是否有文件 沒有就創(chuàng)建

const filePath = path.resolve(__dirname, './log.txt');

// 判斷文件是否存在,如果不存在就創(chuàng)建一個(gè)空文件

if (!fs.existsSync(filePath)) {

fs.writeFileSync(filePath, '');

}

// 獲取url和ip地址

const {url, ip} = req;

// 每個(gè)請(qǐng)求過來的路由信息都保存到日志記錄文件

fs.appendFileSync(path.resolve(__dirname, `./log.txt`), `${url} ${ip}\r\n`);

// 調(diào)用next

next();

}

// 調(diào)用中間件函數(shù)

app.use(recordMiddleWare);

app.get('/login', (req, res) => {

res.send('login success!');

})

app.listen(3000, () => {

console.log('server started at port 3000');

console.log('http://localhost:3000');

})

路由中間件實(shí)踐

運(yùn)行點(diǎn)擊測(cè)試1運(yùn)行點(diǎn)擊測(cè)試2運(yùn)行點(diǎn)擊測(cè)試3

代碼示例:middleware_pratice.js

// 中間件實(shí)踐

/** 需求

* 針對(duì)/admin /setting的請(qǐng)求,要求URL攜帶code=521參數(shù),如未攜帶提示【暗號(hào)錯(cuò)誤】

*/

const express = require('express');

const app = express();

// 定義中間件

function checkCodeMiddleWare(req, res, next) {

// 獲取code

const {code} = req.query;

if (Number(code) === 521) {

next();

} else {

next("【暗號(hào)錯(cuò)誤】");

}

}

//調(diào)用中間件

app.get('/admin', checkCodeMiddleWare, (req, res) => {

res.send('admin success!');

})

//調(diào)用中間件

app.get('/setting', checkCodeMiddleWare, (req, res) => {

res.send('setting success!');

})

app.get('/registry', (req, res) => {

res.send('registry success!');

})

app.get('*', (req, res) => {

res.send('

404 Not Found

');

})

app.listen(3000, () => {

console.log('server started at port 3000');

console.log('http://localhost:3000');

})

靜態(tài)資源中間件

根目錄下新建public文件夾=》新建index.html文件+新建index.css文件代碼如下:

//靜態(tài)資源中間件請(qǐng)求

app.use(express.static(__dirname + '/public'));

運(yùn)行代碼 staticMiddleware.js,下面路徑express/staticMiddleware.js為自己運(yùn)行的文件路徑

node express/staticMiddleware.js

驗(yàn)證

默認(rèn)打開index.html可直接查看css文件

完整代碼示例:

// 靜態(tài)資源中間件

const express = require('express');

const app = express();

//靜態(tài)資源中間件請(qǐng)求

app.use(express.static(__dirname + '/public'));

// 監(jiān)聽端口 啟動(dòng)服務(wù)

app.listen(3000, () => {

console.log("Server running on port 3000");

console.log('http://localhost:3000');

})

靜態(tài)資源中間件注意事項(xiàng)

index.html為默認(rèn)打開的資源靜態(tài)文件與路由規(guī)則app.get(‘/’,()=>{})同時(shí)匹配,誰先匹配誰就響應(yīng),看代碼順序路由響應(yīng)動(dòng)態(tài)資源,靜態(tài)資源中間件響應(yīng)靜態(tài)資源

獲取請(qǐng)求體數(shù)據(jù)body-parser

安裝

npm i body-parser

獲取中間件函數(shù)

處理queryString格式的請(qǐng)求體:const urlParser = bodyParser.urlencoded({extended: false});處理json格式的請(qǐng)求體:const jsonParser = bodyParser.json();

// 獲取中間件函數(shù)

//處理queryString格式的請(qǐng)求體

const urlParser = bodyParser.urlencoded({extended: false});

//處理json格式的請(qǐng)求體

const jsonParser = bodyParser.json();

使用中間件

//獲取請(qǐng)求體數(shù)據(jù)

app.post('/login', urlParser, (req, res) => {

// 獲取請(qǐng)求體數(shù)據(jù)

console.log(req.body);

res.send('用戶名:' + req.body.username + '
密碼:' + req.body.password);

})

完整代碼示例:bodyParser.js

// body-parse獲取請(qǐng)求體

const express = require('express');

const bodyParser = require('body-parser');

const app = express();

// 獲取中間件函數(shù)

//處理queryString格式的請(qǐng)求體

const urlParser = bodyParser.urlencoded({extended: false});

//處理json格式的請(qǐng)求體

const jsonParser = bodyParser.json();

//響應(yīng)login頁面

app.get('/login', urlParser, (req, res) => {

res.sendFile(__dirname + '/login.html');

})

//獲取請(qǐng)求體數(shù)據(jù)

app.post('/login', urlParser, (req, res) => {

// 獲取請(qǐng)求體數(shù)據(jù)

console.log(req.body);

res.send('用戶名:' + req.body.username + '
密碼:' + req.body.password);

})

app.listen(3000, () => {

console.log('Express server started');

console.log('http://localhost:3000');

})

防盜鏈

介紹

比如有的圖片,直接復(fù)制地址顯示到img是拿不到的,說明這個(gè)網(wǎng)站做了防盜鏈處理。判斷源是請(qǐng)求頭里的referer參數(shù)會(huì)攜帶當(dāng)前域名和協(xié)議及其端口進(jìn)行請(qǐng)求。

實(shí)踐

完整代碼示例:

referer.js

const express = require('express');

const app = express();

// 定義全局防盜鏈中間件 判斷請(qǐng)求頭referer

app.use((req, res, next) => {

const referer = req.get('referer');

if (referer) {

// 實(shí)例化

const url = new URL(referer);

const hostname = url.hostname;

console.log(hostname);

if (hostname !== '127.0.0.1') {

res.status(404).send('

404 Not Found

');

return;

}

}

next();

})

// 讀取靜態(tài)資源

app.use(express.static(__dirname + '/public'));

app.listen(3000, () => {

console.log('Express server listening on port 3000');

console.log('http://localhost:3000');

})

public=>index.html

Title

測(cè)試??!

logo

路由模塊化(***)

路由功能代碼進(jìn)行拆分

新建文件夾routes新建homeRouter.js創(chuàng)建單獨(dú)的路由規(guī)則

routermodule.js 代碼示例:

const express = require("express");

const userRouter = require(__dirname + "/routes/userRouter.js");

const adminRouter = require(__dirname + "/routes/adminRouter.js");

const app = express();

app.use(userRouter);

app.use(adminRouter);

app.all("*", function (req, res) {

res.send('404 Not Found');

})

app.listen(3000, () => {

console.log("server started");

console.log('http://localhost:3000');

})

userRouter.js

// user routes

const express = require('express');

const router = express.Router();

router.get('/login', (req, res) => {

res.send('login登錄');

})

router.get('/registry', (req, res) => {

res.send('registry注冊(cè)');

})

module.exports = router;

adminRouter.js

// admin routes

const express = require('express');

const router = express.Router();

router.get('/setting', (req, res) => {

res.send('設(shè)置setting');

})

router.get('/modify', (req, res) => {

res.send('修改setting');

})

module.exports = router;

模版引擎

簡(jiǎn)單介紹

模版引擎是分離用戶界面和業(yè)務(wù)數(shù)據(jù)的一種技術(shù)

ejs

分離HTML和JS的,ejs是一個(gè)高效的JavaScript模版引擎。主要了解ejs,現(xiàn)在不多用了。

安裝

npm i ejs

導(dǎo)入ejs

const ejs = require('ejs');

使用ejs渲染

代碼示例:ejs.js

// ejs初體驗(yàn)

const express = require('express');

const ejs = require('ejs');

const fs = require('fs');

const path = require('path');

const app = express();

// 讀取靜態(tài)資源

app.use(express.static(path.join(__dirname, './public')));

const china = '中國(guó)';

// 讀取html文件

const htmlData = fs.readFileSync(__dirname + '/public/index.html','utf-8').toString();

//使用ejs渲染

const result = ejs.render(htmlData, {china: china});

console.log(result);

代碼示例:index.html

<%= china %>

Title

測(cè)試!!

logo

讀出來了嗎?

<%= china %>

ejs列表渲染

代碼如下:ejs_xiyou.js

// ejs列表渲染

/** 需求

* 渲染ul li 西游數(shù)組

*/

const ejs = require('ejs');

const fs = require('fs');

const xiyou = ['唐僧', '孫悟空', '沙僧', '豬八戒'];

const htmlData = fs.readFileSync(__dirname + '/ejs_xiyou.html').toString()

const result = ejs.render(htmlData, {xiyou: xiyou});

console.log(result);

代碼如下:ejs_xiyou.html

    <% xiyou.forEach(item=>{ %>

  • <%= item %>
  • <% }) %>

ejs條件渲染

js如上html如下 代碼示例:

<% if(isLogin){ %>

登錄成功

<% }else{ %>

登錄失敗

<% } %>

express中使用ejs

設(shè)置模板引擎

app.set('view engine', 'ejs');

設(shè)置模板文件存放位置 新建view文件夾=》views新建.ejs文件,比如home.ejs

app.set('views',path.resolve(__dirname,'./views'))

render響應(yīng)

res.render('home',{title})

創(chuàng)建模版文件 其實(shí)就是.ejs文件,但其實(shí)就是類html文件,主要得含有如下代碼:

<%= title %>

完整代碼示例:express_ejs.js

const express = require("express");

const ejs = require("ejs");

const path = require("path");

const app = express();

// 1-設(shè)置模版引擎

app.set("view engine", "ejs");

// 2-設(shè)置模版文件存放位置

app.set("views", path.resolve(__dirname, "./views"));

app.get('/home', (req, res) => {

const title = 'Home頁面';

// 3-render響應(yīng)

res.render("home", {title});

// 創(chuàng)建模版文件 home.ejs

})

app.all('*', (req, res) => {

res.send('404 Not Found');

})

app.listen(3000, () => {

console.log("Server is running on port 3000");

console.log('http://localhost:3000');

});

完整代碼:views=>home.ejs

Title

測(cè)試:

<%= title %>

express-generator工具

通過應(yīng)用生成器express-generator快速創(chuàng)建一個(gè)應(yīng)用骨架

安裝

npx命令來運(yùn)行(包含Node.js8.2.0及更高的版本中)

npx express-generator

npm方式

npm i -g express-generator

創(chuàng)建文件夾

語法 express -e <文件夾名稱>

express -e generator

查看相關(guān)命令

express -h

查看文件上傳報(bào)文

代碼示例 portrait.js

const express = require('express');

const path = require('path');

const app = express();

//設(shè)置模板引擎

app.set('view engine', 'ejs');

//設(shè)置模板引擎存放文件位置

app.set('views', path.resolve(__dirname, './views'));

// render響應(yīng)

app.get('/portrait', (req, res) => {

res.render('portrait');

})

app.post('/portrait', (req, res) => {

console.log(req);

res.send('成功!');

})

app.listen(3000, () => {

console.log('Express server started');

console.log('http://localhost:3000');

});

完整代碼portrait.ejs

查看文件上傳報(bào)文

用戶名:

頭像

處理文件上傳

借助庫formidable 使用參考注意:Commonjs 使用require引入需要安裝V2版本的,V3的只能使用import 引入創(chuàng)建public文件夾=》images文件夾

代碼示例:

const express = require('express');

const path = require('path');

const formidable = require('formidable').formidable;

const app = express();

//設(shè)置模板引擎

app.set('view engine', 'ejs');

//設(shè)置模板引擎存放文件位置

app.set('views', path.resolve(__dirname, './views'));

// render響應(yīng)

app.get('/portrait', (req, res) => {

res.render('portrait');

})

// 響應(yīng)靜態(tài)資源——方便訪問上傳的圖片

app.use(express.static(path.resolve(__dirname, './public')));

app.post('/portrait', (req, res) => {

const form = formidable({

multiple: true,

// 設(shè)置上傳文件的保存目錄

uploadDir: path.join(__dirname, './public/images'),

// 保持文件后綴

keepExtensions: true

})

form.parse(req, (err, fields, files) => {

if (err) {

next(err);

return;

}

// 存放非文件的字段

// console.log(fields);

// 存放文件

// console.log(files);

// 服務(wù)器保存存放的照片的訪問url

const url = '/images/' + files.portrait.newFilename;

res.send(url);

});

})

app.listen(3000, () => {

console.log('Express server started');

console.log('http://localhost:3000');

});

mongoDB

介紹

基于分布式文件存儲(chǔ)的數(shù)據(jù)庫,官方網(wǎng)址

相比于純文件管理數(shù)據(jù),數(shù)據(jù)庫管理數(shù)據(jù)優(yōu)點(diǎn):

速度更快擴(kuò)展性更強(qiáng)安全性更強(qiáng)

核心概念

數(shù)據(jù)庫:又稱數(shù)據(jù)倉(cāng)庫,可存放很多集合集合:類似于JS中的數(shù)據(jù),在集合中可以存放很多文檔文檔:數(shù)據(jù)庫中的最小單位,類似JS中的對(duì)象

下載安裝與啟動(dòng)

下載地址 這邊記錄下自己的mac安裝教程,可根據(jù)直接的電腦系統(tǒng)去搜搜安裝

參考mac安裝mongoDB數(shù)據(jù)庫

具體步驟:

進(jìn)入MongoDB官網(wǎng)進(jìn)行下載下載完畢并且解壓,重新命名為 【mongodb】文件夾打開訪達(dá) 按住快捷鍵command+shift+g 前往/usr/local路徑將解壓并命名好的【mongodb】文件夾拖入到這個(gè)路徑下配置環(huán)境變量,在根目錄輸入open -e .zshrc打開.zshrc文件夾。(注意:我的終端是zsh,如果你們的終端是bash的話應(yīng)該輸入open .bash_profile)在里面添加一下代碼

export PATH=${PATH}:/usr/local/mongodb/bin

保存好了文件后,需要執(zhí)行改文件,在根目錄輸入 source .zshrc 來進(jìn)行執(zhí)行。(注意:我的終端是zsh,如果你們的終端是bash的話應(yīng)該輸入source .bash_profile)在此執(zhí)行一下命令(確保是在根目錄 不確定就執(zhí)行 cd ~)

mongod --version

安裝mongodb成功了后,那存的數(shù)據(jù)和日志記錄放哪呢。這就需要建立data和log文件夾了。進(jìn)入到mongodb文件夾的目錄下

進(jìn)行mongodb文件夾下

cd /usr/local/mongodb

創(chuàng)建

mkdir data log

給這data文件夾賦予讀寫權(quán)限,輸入電腦開機(jī)密碼,密碼輸入的時(shí)候看不見。

sudo chown [你的用戶名] /usr/local/mongodb/data

給這log文件夾賦予讀寫權(quán)限,輸入電腦開機(jī)密碼,密碼輸入的時(shí)候看不見。

sudo chown [你的用戶名] /usr/local/mongodb/log

在mongondb路徑下啟動(dòng)mongoDB:mongod --fork --dbpath data --logpath log/mongo.log --logappend 這句命令,看到child process started successfully, parent exiting這句話就成功啟動(dòng)服務(wù)了

mongod --fork --dbpath data --logpath log/mongo.log --logappend

使用mongo指令 瀏覽器進(jìn)入http://127.0.0.1:27017/ 關(guān)閉數(shù)據(jù)庫服務(wù) (直接關(guān)閉)針對(duì)于(mac zsh)

sudo pkill -f mongod

再次訪問上面網(wǎng)址就會(huì)失敗

mac zsh配置啟動(dòng)腳本

創(chuàng)建一個(gè)啟動(dòng)腳本文件,以確保命令在正確的目錄中運(yùn)行:

創(chuàng)建腳本文件:

touch start_mongo.sh

編輯腳本文件:

nano start_mongo.sh

添加以下內(nèi)容:

#!/bin/zsh

cd /usr/local/mongodb

mongod --fork --dbpath data --logpath log/mongo.log --logappend

保存并退出: 保存文件并退出編輯器(按Ctrl+X退出,按Y保存,回車enter退出)。

PS:同理建立了關(guān)閉mongods腳本。 命令為:

sudo pkill -f mongod

賦予執(zhí)行權(quán)限:

chmod +x start_mongo.sh

運(yùn)行腳本: 現(xiàn)在你可以運(yùn)行腳本來啟動(dòng)MongoDB:

./start_mongo.sh

mac下載可視化工具Robomongo(studio3T)

下載地址參考可視化工具Robomongo(studio3T)安裝使用

文檔命令

插入文檔

語法:db.集合名.insert(文檔對(duì)象)

db.user.insert({username:'ll',age:18})

查詢文檔

語法:db.集合名.find(查詢條件)

db.user.find({age:20})

更新文檔

語法:db.集合名.update(查詢條件,新的文檔)

db.user.find({name:'張三'},{$set:{age:20}})

刪除文檔

語法:db.集合名.remove(查詢條件)

db.user.remove({name:'張三'})

mongoose

連接數(shù)據(jù)庫

代碼及說明如下:

// mongoose使用 前提得啟動(dòng)mongoose

// 1-安裝依賴

// 2-引入依賴

const mongoose = require('mongoose');

// 3-連接mongodb服務(wù)

mongoose.connect('mongodb://127.0.0.1:27017/user');

// 補(bǔ)充說明:1-設(shè)置strictQuery為true

mongoose.set('strictQuery', true);

// 設(shè)置回調(diào)

// 連接成功的回調(diào) 補(bǔ)充說明:2-once:事件回調(diào)函數(shù)只執(zhí)行一次

mongoose.connection.on('open', () => {

console.log('連接成功!');

})

// 連接錯(cuò)誤的回調(diào)

mongoose.connection.on('error', (err) => {

console.log('連接錯(cuò)誤:')

console.error(err);

})

// 連接關(guān)閉的回調(diào)

mongoose.connection.on('close', () => {

console.log('連接關(guān)閉');

})

// 關(guān)閉連接

setTimeout(function () {

console.log('連接關(guān)閉');

mongoose.disconnect();

}, 2000)

…mongoose大致學(xué)到這里,需要的在看文檔好了…

會(huì)話控制

介紹

所謂會(huì)話控制是對(duì)會(huì)話進(jìn)行控制。 因?yàn)镠TTP是一個(gè)無狀態(tài)的協(xié)議,它沒有辦法區(qū)分多次的請(qǐng)求是否來自同一客戶端,無法區(qū)分用戶,而產(chǎn)品中又大量存在這樣的需求,所以我們需要通過會(huì)話控制解決該問題。

常見的會(huì)話控制方式:

CookieSessionToken

Cookie

cookie是HTTP服務(wù)器發(fā)送到用戶瀏覽器并保存在本地的一小塊數(shù)據(jù)

cookie是保存在瀏覽器的一小塊數(shù)據(jù)cookie是按照域名劃分保存的

特點(diǎn):

瀏覽器向服務(wù)器發(fā)送請(qǐng)求時(shí),會(huì)自動(dòng)將當(dāng)前域名可用的cookie設(shè)置在請(qǐng)求頭中,然后傳遞給服務(wù)器。請(qǐng)求頭的名字也叫cookie 所以將cookie理解為一個(gè)http的請(qǐng)求頭也是可以的

瀏覽器Cookie

禁用cookie

這個(gè)操作一般不做

網(wǎng)站——隱私設(shè)置和安全性設(shè)置——常規(guī)設(shè)置——阻止所有cookie

刪除cookie

網(wǎng)站——隱私設(shè)置和安全性設(shè)置——清除相應(yīng)網(wǎng)站數(shù)據(jù)

查看cookie

edge瀏覽器查看——輸入cookie查詢——cookie和網(wǎng)站數(shù)據(jù)——點(diǎn)擊下拉查看谷歌瀏覽器查看——網(wǎng)站鏈接旁的左上方小鎖——cookie和網(wǎng)站數(shù)據(jù)——點(diǎn)擊查看

express Cookie

設(shè)置cookie

eg:res.cookie(‘name’,‘lhm’,{})

const express = require('express');

const app = express();

app.get('/set-cookie',(req,res)=>{

res.cookie('name','lhm');//會(huì)在瀏覽器關(guān)閉的時(shí)候,銷毀

res.cookie('name','lhm',{maxAge:60 * 1000}); //maxAge最大存活時(shí)間 單位毫秒 但是瀏覽器中存的是秒s

res.send('home');

})

刪除cookie

eg:res.clearCookie(‘name’)

const express = require('express');

const app = express();

app.get('/remove-cookie',(req,res)=>{

res.clearCookie('name');

res.send('remove');

})

讀取cookie

工具庫cookie-parse,使用這個(gè)為一個(gè)cookie解析中間件

安裝依賴

npm i cookie-parse

引入使用

const express = require('express');

const cookieParse = require('cookie-parse');

const app = express();

app.use(cookieParse());

獲取cookie值

req.cookies獲取到cookie值

app.get('/get-cookie',(req,res)=>{

console.log(req.cookies);

console.log(res.cookies.name);

})

session

保存到服務(wù)器的一塊兒數(shù)據(jù),保存當(dāng)前訪問的用戶的相關(guān)信息

作用:

實(shí)現(xiàn)會(huì)話控制,可以識(shí)別用戶的身份,快速獲取當(dāng)前用戶的相關(guān)信息

運(yùn)行流程:

填寫賬號(hào)和密碼校驗(yàn)身份,校驗(yàn)填入通過后創(chuàng)建session信息,然后通過session_id的值通過響應(yīng)頭返回給瀏覽器有了cookie,下載發(fā)送請(qǐng)求會(huì)自動(dòng)攜帶cookie,服務(wù)器通過cookie和session_id的值確定用戶的身份

session與cookie區(qū)別

存在位置不同。cookie存在瀏覽器,session 服務(wù)端安全性。cookie明文存在客戶端,session是存在服務(wù)器,安全性相對(duì)較好網(wǎng)絡(luò)傳輸量。 cookie設(shè)置內(nèi)容過多會(huì)增加保溫體積,影響傳輸效率。session數(shù)據(jù)存儲(chǔ)在服務(wù)器,只是通過cookie傳遞id,所以不影響傳輸效率存儲(chǔ)限制。cookie保存的數(shù)據(jù)不超過4k 且單個(gè)域名下的存儲(chǔ)數(shù)量有限。session數(shù)據(jù)存儲(chǔ)在服務(wù)器,沒有限制。

視頻的基礎(chǔ)知識(shí)大致學(xué)到這里,下面似乎涉及用處小,需要的時(shí)候還有機(jī)會(huì)的話再更新吧…

完結(jié)撒花~~~

柚子快報(bào)激活碼778899分享:vim node.js學(xué)習(xí)

http://yzkb.51969.com/

推薦鏈接

評(píng)論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。

轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://m.gantiao.com.cn/post/19254656.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄