1 命令行窗口
1.1. 命令行窗口(小黑屏)、CMD窗口、終端、shell
開始菜單 -> 運行 -> cmd -> 回車
直接url欄中輸入cmd
1.2. 常用指令
dir 列出當前目錄下面的所有文件
cd 目錄名 進入到指定的目錄
md 目錄名 創建一個文件夾
rd 目錄名 刪除一個文件夾
文件名.后綴名 打開文件
D: 進入D盤
1.3. 目錄
. 表示當前目錄
.. 表示上一級目錄
1.4. 環境變量(windows系統中變量)
path:環境變量中保存的是一個一個的路徑,路徑之間使用;隔開
里面放的都是路徑,該路徑下的文件,可以直接打開
作用:當我們在命令行窗口打開一個文件,或調用一個程序時,系統會首選在當前目錄下尋找文件程序,如果找到了則直接打開,如果沒有找到則會依次到環境變量path的路徑中尋找,直到找到為止,如果沒有找到則報錯。
所以我們可以將一些經常需要訪問的程序和文件的路徑添加到path中,這樣我們就可以在任意位置來訪問這些文件和程序了。
2 進程和線程
2.1. 進程
進程負責為程序的運行提供必備的環境。
進程就相當于工廠中的車間。
2.2. 線程
線程是計算機中的最小的計算單位,線程負責執行進程中的程序。
線程就相當于工廠中的工人。
2.3. 單線程
js是單線程的。
2.4. 多線程
java是多線程的。
3 Nodejs
是一個能夠在服務器端運行JavaScript的開放源代碼、跨平臺JavaScript運行環境。
采用Google開發的V8引擎運行js代碼,使用事件驅動、非阻塞和異步I/O模型等技術來提高性能,可優化應用程序的傳輸量和規模。
3.1. I/O(Input/Output)
I/O操作指的是對磁盤的讀寫操作
3.2. Node
Node是對ES標準的一種實現,Node也是一個JS引擎
通過Node可以使js代碼再服務器端運行
Node僅僅對ES標準進行了實現,所以在Node中不包含DOM 和 BOM
Node中可以使用ES所有的內建對象
(1) String Number Boolean Math Date RegExp Function Object Array
(2) 可以使用 console 也可以使用定時器(setTimeout() setInterval())
Node 可以在后臺來編寫服務器
Node編寫服務器都是單線程的服務器
(1) 進程就是一個一個的工作計劃(工廠中的車間)
(2) 線程是計算機最小的運算單位(工廠中的工人)
(3) 線程是干活的
傳統的服務器都是多線程的
(1) 每進來一個請求,就創建一個線程去處理請求
Node的服務器是單線程的
(1) Node處理請求時是單線程,但是在后臺擁有一個I/O線程池
運行:node XXX.js運行
3.3. 為什么選擇Node
使用JavaScript語法開發后端應用
一些公司要求前端工程師掌握Node開發
生態系統活躍,有大量開源庫可以使用
前端開發工具大多基于Node開發
3.4. Node是什么
Node是一個基于Chrome V8引擎的JavaScript代碼運行環境。
瀏覽器(軟件)能夠運行JavaScript代碼,瀏覽器就是JavaScript代碼的運行環境
Node(軟件)能夠運行JavaScript代碼,Node就是JavaScript代碼的運行環境
LTS = Long Term Support 長期支持版 穩定版
Current 擁有最新特性 實驗版
3.5. Node.js 的組成
JavaScript 由三部分組成,ECMAScript,DOM,BOM。
Node.js是由ECMAScript及Node 環境提供的一些附加API組成的,包括文件、網絡、路徑等等一些更加強大的 API。(ECMAScript + Node模塊API)
4 模塊化
JavaScript開發弊端:
JavaScript在使用時存在兩大問題,文件依賴和命名沖突。
軟件中的模塊化開發:
一個功能就是一個模塊,多個模塊可以組成完整應用,抽離一個模塊不會影響其他功能的運行。
4.1. 模塊化
將一個完整的程序分成一個一個小的程序,降低耦合度,方便代碼的復用。
在node中,一個js文件就是一個模塊。
在node中,每一個js文件中的js代碼 都是獨立運行在一個函數中
(function(){
....
})()
而不是全局作用域,所以一個模塊中的變量和函數在其他模塊中無法訪問。
我們可以通過 exports 來向外部暴露變量和方法,只需要將需要暴露給外部的變量或方法設置為exports的屬性即可。
exports.x = 100
exports.fn = function(){}
Node.js規定一個JavaScript文件就是一個模塊,模塊內部定義的變量和函數默認情況下在外部無法得到。
模塊內部可以使用exports對象進行成員導出,使用require方法導入其他模塊。
4.2. 引入其他的模塊
在node中,通過require()函數來引入外部的模塊。
require() 可以傳遞一個文件的路徑作為參數,node將會自動根據該路徑來引入外部模塊。
這里路徑,如果使用相對路徑,必須以.或..開頭。
使用require()引入模塊以后,該函數會返回一個對象,這個對象代表的是引入的模塊。
4.3. 模塊標識
我們使用require()引入外部模塊時,使用的就是模塊標識。
require( './02module.js ') './02module.js'這個路徑就是一個模塊標識。
我們可以通過模塊標識來找到指定的模塊。
模塊分成兩大類:
核心模塊
由node引擎提供的模塊
核心模塊的標識就是模塊的名字 (或者npm下載的模塊,都是直接寫名字)
文件模塊
由用戶自己創建的模塊
文件模塊的標識就是文件的路徑 (可以是絕對路徑 或 相對路由)相對路徑使用 . 或 .. 開頭。
4.4. 什么是系統模塊
Node運行環境提供的API. 因為這些API都是以模塊化的方式進行開發的, 所以我們又稱Node運行環境提供的API為系統模塊
4.4.1. 系統模塊fs 文件操作:
f:file 文件 ,s:system 系統,文件系統。
const fs = require('fs');
讀取文件內容
fs.readFile('文件路徑/文件名稱'[,'文件編碼'], callback);
寫入文件內容
fs.writeFile('文件路徑/文件名稱', '數據', callback);
const content = '<h3>正在使用fs.writeFile寫入文件內容</h3>';
fs.writeFile('../index.html', content, err => {
if (err != null) {
console.log(err);
return;
}
console.log('文件寫入成功');
});
4.4.2.?系統模塊path 路徑操作:
為什么要進行路徑拼接
不同操作系統的路徑分隔符不統一
/public/uploads/avatar
Windows 上是 \ /
Linux 上是 /
路徑拼接語法:
path.join('路徑', '路徑', ...)
// 導入path模塊
const path = require('path');
// 路徑拼接
let finialPath = path.join('itcast', 'a', 'b', 'c.css');
// 輸出結果 itcast\a\b\c.css
console.log(finialPath);
相對路徑VS絕對路徑:
大多數情況下使用絕對路徑,因為相對路徑有時候相對的是命令行工具的當前工作目錄
在讀取文件或者設置文件路徑時都會選擇絕對路徑
使用__dirname獲取當前文件所在的絕對路徑
4.5.?什么是第三方模塊
別人寫好的、具有特定功能的、我們能直接使用的模塊即第三方模塊,由于第三方模塊通常都是由多個文件組成并且被放置在一個文件夾中,所以又名包。
第三方模塊有兩種存在形式:
以js文件的形式存在,提供實現項目具體功能的API接口。
以命令行工具形式存在,輔助項目開發。
npmjs.com:第三方模塊的存儲和分發倉庫。
4.5.1.?第三方模塊 nodemon
nodemon是一個命令行工具,用以輔助項目開發。
在Node.js中,每次修改文件都要在命令行工具中重新執行該文件,非常繁瑣。
使用步驟:
使用npm install nodemon –g 下載它
在命令行工具中用nodemon命令替代node命令執行文件
5 global
5.1. 全局變量
在node中有一個全局變量 global, 它的作用和網頁中window類似。
在全局中創建的變量都會作為global的屬性保存。
在全局中創建的函數都會作為global的方法保存。
console.log(global);
Node中全局對象下有以下方法,可以在任何地方使用,global可以省略。
console.log() 在控制臺中輸出
setTimeout() 設置超時定時器
clearTimeout() 清除超時時定時器
setInterval() 設置間歇定時器
clearInterval() 清除間歇定時器
5.2. 模塊作用域
當node在執行模塊中的代碼時,它會首先在代碼的最頂部,添加如下代碼
function (exports, require, module, __filename, __dirname) {
在代碼的最底部,添加如下代碼
}
實際上模塊中的代碼都是包裝在一個函數中執行的,并且在函數執行時,同時傳遞進了5個實參
exports 該對象用來將變量或函數暴露到外部
require 函數,用來引入外部模塊
module 代表的是當前模塊本身 exports就是module的屬性
既可以使用 exports 導出,也可以使用module.exports 導出
__filename 當前模塊的完整路徑
__dirname 當前模塊所在文件夾的完整路徑
查看的方式:
console.log(arguments);
arguments.callee:保存的是當前執行的函數的對象
console.log(arguments.callee+'');
console.log(module.exports == exports);
console.log(__filename);
console.log(__dirname);
5.2.1. exports 和 module.exports
exports 實際指向 module.exports。
通過exports只能使用.的方式來向外暴露內部變量
exports.xxx?= xxx
而module.exports既可以通過.的形式,也可以直接賦值
module.exports.xxx?= xxx
module.exports = {}
6 包
6.1. 什么是包
包規范允許我們將一組相關的模塊組合到一起,形成一組完整的工具。
包規范由 包結構 和 包描述文件 兩個部分組成。
包結構:用于組織包中的各種文件。
包描述文件:描述包的相關信息,以供外部讀取分析。
6.2. 包結構
包實際上就是一個壓縮文件,解壓以后還原目錄。符合規范的目錄,應該包含如下文件:
package.json 描述文件
bin 可執行二進制文件
lib js代碼
doc 文檔
test 單元測試
6.3. 描述文件
package.json
項目描述文件,記錄了當前項目信息,例如項目名稱、版本、作者、github地址、當前項目依賴了哪些第三方模塊等。
使用npm init -y命令生成。
項目依賴:
在項目的開發階段和線上運營階段,都需要依賴的第三方包,稱為項目依賴。
使用npm install 包名命令下載的文件會默認被添加到 package.json 文件的 dependencies 字段中。
在項目的開發階段需要依賴,線上運營階段不需要依賴的第三方包,稱為開發依賴。
使用npm install 包名 --save-dev命令將包添加到package.json文件的devDependencies字段中。
dependencies 依賴 當前包依賴的其他包
devDependencies 開發環境依賴
package-lock.json文件的作用:
鎖定包的版本,確保再次下載時不會因為包版本不同而產生問題。
加快下載速度,因為該文件中已經記錄了項目所依賴第三方包的樹狀結構和包的下載地址,重新安裝時只需下載即可,不需要做額外的工作。
6.4. NPM
6.4.1. NPM(Node Package Manager)
npm 幫助其完成了第三方模塊的發布、安裝和依賴等。
借助NPM,Node與第三方模塊之間形成了很好的一個生態系統。
命令:
npm -v :查看npm的版本
npm version :查看所有模塊的版本
npm :幫助說明
npm search 包名 :搜索模塊包
npm install/i 包名 :在當前目錄安裝包
npm install/i 包名 -g :全局模式安裝包 (全局安裝的包一般都是一些工具)
npm remove/r 包名 :刪除一個模塊
npm uninstall 包名 :刪除一個模塊
npm update :升級全部包
npm update 包名 :升級指定包
npm install 包名 --save :安裝包并添加到依賴中 重要
npm install :下載當前項目所依賴的包
npm install 文件路徑 :從本地安裝
npm install 包名 --registry=地址 :從鏡像源安裝
npm config set registry 地址 :設置鏡像源
npm install -g 就是npm install --global
npm install -D 就是npm install --save-dev
(1) devDependencies 里面的包只用于開發環境,不用于生產環境
npm install -S 就是npm install --save
(1) 而 dependencies 是需要發布到生產環境的
npm view 包名 versions 查看所有版本 npm view 包名 version 查看最高版本
npm i 包名@版本 安裝指定版本的包
全局安裝與本地安裝:
命令行工具:全局安裝
庫文件:本地安裝
6.4.2. cnpm中國 npm 鏡像的客戶端
npm install cnpm -g :安裝cnpm(cnpm 是中國 npm 鏡像的客戶端)
npm install cnpm -g --registry=https://registry.npm.taobao.org (國內安裝)
6.4.3. npm修改或切換鏡像地址
方式一:直接編輯npm的配置文件
npm config edit
直接修改registry的地址
registry=https://registry.npm.taobao.org
方式二:用代碼更改npm的配置文件
npm config set registry?http://registry.npm.taobao.org
這段代碼即將鏡像改為淘寶鏡像
方式三:使用nrm管理registry地址
安裝nrm
npm install -g nrm
查看鏡像列表
nrm ls
nrm ls 報錯解決方案:
//const NRMRC = path.join(process.env.HOME, '.nrmrc');(注掉)
const NRMRC = path.join(process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'], '.nrmrc');
切換鏡像
nrm use taobao
在nrm添加自己的鏡像地址
nrm add r_name r_url
刪除
nrm del r_name
測試鏡像的相應速度
nrm test r_namer
6.4.4. yarn
方式一:使用安裝包安裝
官方下載安裝包,https://yarnpkg.com/zh-Hans/docs/install,安裝完畢后,一定要配置環境變量。
方式二:使用npm安裝
npm i yarn -g
常用命令:
yarn / yarn install 等同于npm install 批量安裝依賴
yarn add xxx 等同于 npm install xxx --save 安裝指定包到指定位置
yarn remove xxx 等同于 npm uninstall xxx --save 卸載指定包
yarn add xxx --dev 等同于 npm install xxx --save-dev
yarn upgrade 等同于 npm update 升級全部包
yarn global add xxx 等同于 npm install xxx -g 全局安裝指定包
6.4.5. npx
npm 從5.2版開始,增加了 npx 命令。
Node 自帶 npm 模塊,所以可以直接使用 npx 命令。萬一不能用,就要手動安裝一下。
npm install -g npx
調用項目安裝的模塊:
npx 想要解決的主要問題,就是調用項目內部安裝的模塊。
npm install -D mocha
一般來說,調用 Mocha ,只能在項目腳本和 package.json 的scripts字段里面, 如果想在命令行下調用,必須像下面這樣。
node-modules/.bin/mocha --version
npx 就是想解決這個問題,讓項目內部安裝的模塊用起來更方便,只要像下面這樣調用就行了。
npx mocha --version
npx 的原理很簡單,就是運行的時候,會到node_modules/.bin路徑和環境變量$PATH里面,檢查命令是否存在。
由于 npx 會檢查環境變量$PATH,所以系統命令也可以調用。
npx ls
注意,Bash 內置的命令不在$PATH里面,所以不能用。比如,cd是 Bash 命令,因此就不能用npx cd。
避免全局安裝模塊:
除了調用項目內部模塊,npx 還能避免全局安裝的模塊。比如,create-react-app這個模塊是全局安裝,npx 可以運行它,而且不進行全局安裝。
npx create-react-app my-react-app
上面代碼運行時,npx 將create-react-app下載到一個臨時目錄,使用以后再刪除。所以,以后再次執行上面的命令,會重新下載create-react-app。
下載全局模塊時,npx 允許指定版本。
npx uglify-js@3.1.0 main.js -o ./dist/main.js
上面代碼指定使用 3.1.0 版本的uglify-js壓縮腳本。
注意,只要 npx 后面的模塊無法在本地發現,就會下載同名模塊。比如,本地沒有安裝http-server模塊,下面的命令會自動下載該模塊,在當前目錄啟動一個 Web 服務。
npx http-server
--no-install 參數和--ignore-existing 參數:
如果想讓 npx 強制使用本地模塊,不下載遠程模塊,可以使用--no-install參數。如果本地不存在該模塊,就會報錯。
npx --no-install http-server
反過來,如果忽略本地的同名模塊,強制安裝使用遠程模塊,可以使用--ignore-existing參數。比如,本地已經全局安裝了create-react-app,但還是想使用遠程模塊,就用這個參數。
npx --ignore-existing create-react-app my-react-app
使用不同版本的 node:
利用 npx 可以下載模塊這個特點,可以指定某個版本的 Node 運行腳本。它的竅門就是使用 npm 的 node 模塊。
npx node@0.12.8 -v
上面命令會使用 0.12.8 版本的 Node 執行腳本。原理是從 npm 下載這個版本的 node,使用后再刪掉。
某些場景下,這個方法用來切換 Node 版本,要比 nvm 那樣的版本管理器方便一些。
-p 參數:
-p參數用于指定 npx 所要安裝的模塊,所以上一節的命令可以寫成下面這樣。
npx -p node@0.12.8 node -v
上面命令先指定安裝node@0.12.8,然后再執行node -v命令。
-p參數對于需要安裝多個模塊的場景很有用。
npx -p lolcatjs -p cowsay [command]
-c 參數:
如果 npx 安裝多個模塊,默認情況下,所執行的命令之中,只有第一個可執行項會使用 npx 安裝的模塊,后面的可執行項還是會交給 Shell 解釋。
npx -p lolcatjs -p cowsay 'cowsay hello | lolcatjs'
上面代碼中,cowsay hello | lolcatjs執行時會報錯,原因是第一項cowsay由 npx 解釋,而第二項命令localcatjs由 Shell 解釋,但是lolcatjs并沒有全局安裝,所以報錯。
-c參數可以將所有命令都用 npx 解釋。有了它,下面代碼就可以正常執行了。
npx -p lolcatjs -p cowsay -c 'cowsay hello | lolcatjs'
-c參數的另一個作用,是將環境變量帶入所要執行的命令。舉例來說,npm 提供當前項目的一些環境變量,可以用下面的命令查看。
npm run env | grep npm_
-c參數可以把這些 npm 的環境變量帶入 npx 命令。
npx -c 'echo "$npm_package_name"'
上面代碼會輸出當前項目的項目名。
執行 GitHub 源碼:
npx 還可以執行 GitHub 上面的模塊源碼。
執行 Gist 代碼
npx?https://gist.github.com/zkat/4bc19503fe9e9309e2bfaa2c58074d32
執行倉庫代碼
npx github:piuccio/cowsay hello
注意,遠程代碼必須是一個模塊,即必須包含package.json和入口腳本。
6.5. Node.js中模塊加載機制
模塊查找規則-當模塊擁有路徑但沒有后綴時:
require('./find.js');
require('./find');
require方法根據模塊路徑查找模塊,如果是完整路徑,直接引入模塊。
如果模塊后綴省略,先找同名JS文件再找同名JS文件夾。
如果找到了同名文件夾,找文件夾中的index.js。
如果文件夾中沒有index.js就會去當前文件夾中的package.json文件中查找main選項中的入口文件。
如果找指定的入口文件不存在或者沒有指定入口文件就會報錯,模塊沒有被找到。
模塊查找規則-當模塊沒有路徑且沒有后綴時:
require('find');
Node.js會假設它是系統模塊。
Node.js會去node_modules文件夾中。
首先看是否有該名字的JS文件。
再看是否有該名字的文件夾。
如果是文件夾看里面是否有index.js。
如果沒有index.js查看該文件夾中的package.json中的main選項確定模塊入口文件。
否則找不到報錯。
7 文件系統
7.1. Buffer(緩沖區)
Buffer的結構和數組很像,操作的方法也和數組類似
數組中不能存儲二進制文件,而Buffer就是專門用來存儲二進制數據
使用buffer不需要引入模塊,直接使用即可
在buffer中存儲的都是二進制數據,但是在顯示時都是以16進制的形式顯示
buffer中每一個元素的范圍是從 00 - ff 0 - 255
00000000 - 11111111
計算機中 一個0 或 一個1 我們稱為1位(bit)
8bit = 1byte(字節)
1024byte = 1kb
1024kb = 1mb
1024mb = 1gb
1024gb = 1tb
buffer中的一個元素,占用內存中的一個字節
buffer的大小一旦確定,則不能修改,buffer實際上是對底層內存的直接操作
Buffer.from(str) 將一個字符串轉換位為Buffer
Buffer.alloc(size) 創建一個指定大小的Buffer(并將內存中的數據清空)
Buffer.allocUnsafe(size) 創建一個指定大小的Buffer,但是可能包含敏感數據(分配空間的時候,沒有清空里面的數據,性能會好一些)
buf.toString() 將緩沖區中的數據轉換為字符串
buf.length 占用內存的大小
在UTF-8編碼中,1個漢字占用3個字節
buf[2] = 0xaa 十六進制數,以0x開頭
buf[3] = 556 只能保存8位,前面的會省略掉
buf[2].toString(16) 轉16進制
buf3[2].toString(2) 轉2進制
7.2. 文件系統
文件系統(File System)
文件系統簡單來說就是通過node來操作系統中的文件
使用文件系統,需要先引入fs模塊,fs是核心模塊,直接引入不需要下載
fs模塊中所有的操作都有兩種形式可供選擇 同步和異步。
同步文件系統會阻塞程序的執行,也就是除非操作完畢,否則不會向下執行代碼。
異步文件系統不會阻塞程序的執行,而是在操作完成時,通過回調函數將結果返回。
7.3. 文件的寫入
步驟:
打開文件
fs.openSync(path[, flags, mode])
- path 要打開文件的路徑
- flags 打開文件要做的操作的類型
- r 只讀的
- w 可寫的
- mode 設置文件的操作全選,一般不傳
返回值:
- 該方法會返回一個文件的描述符作為結果,我們可以通過該描述符來對文件進行各種操作
向文件中寫入內容
fs.writeSync(fd, string[, position[, encoding]])
- fd 文件的描述符,需要傳遞要寫入的文件的描述符
- string 要寫入的內容
- position 寫入的起始位置
- encoding 寫入的編碼,默認utf-8
保存并關閉文件
fs.closeSync(fd)
- fd 要關閉的文件的描述符
7.4. 異步文件寫入
步驟:
打開文件
fs.open(path[, flags[, mode]], callback)
- 用來打開一個文件
- 異步調用的方法,結果都是通過回調函數的參數返回的
- 回調函數兩參數:
err 錯誤對象,如果沒有錯誤則為null
fd 文件的描述符
向文件中寫入內容
fs.write(fd, buffer[, offset[, length[, position]]], callback)
- 用來異步寫入一個文件
保存并關閉文件
fs.close(fd, callback)
- 用來關閉文件
7.5. 簡單文件寫入
fs.writeFileSync(file, data[, options])
fs.writeFile(file, data[, options], callback)
- file 要操作的文件的路徑
- data 要寫入的數據
- options 選項,可以對寫入進行一些設置
- flag r 只讀 w 可寫 a 追加
- callback 當寫入完成以后執行的函數
步驟:
引入fs模塊
var fs = require('fs')
寫入
fs.writeFile('C:\Users\bing\Desktop\hello.txt','內容',{flag:'a'},function(err){
if(!err){
console.log('寫入成功~~~');
}else{
console.log(err);
}
})
7.6. 流式文件寫入
同步,異步,簡單文件的寫入都不適合大文件的寫入,性能較差,容易導致內存溢出
流式文件寫入步驟:
創建一個可寫流
var ws = fs.createWriteStream(path[, options])
- 可以用來創建一個可寫流
- path,文件路徑
- options,配置的參數
可以通過監聽流的open和close事件來監聽流的打開和關閉
(1) on 和 once 綁定事件
(2) once 可以為對象綁定一個一次性的事件,該事件將會在觸發一次以后自動失效
ws.once('open',function(){
console.log('流打開了~~~');
})
ws.once('close',function(){
console.log('流關閉了~~~');
})
通過write方法向文件中輸出內容
ws.write('通過可寫流寫入文件的內容')
ws.write('helloworld')
關閉流
ws.end()
7.7. 簡單文件讀取
fs.readFileSync(path[, options])
fs.readFile(path[, options], callback)
- path 要讀取的文件的路徑
- options 讀取的選項
- callback 回調函數,通過回調函數將讀取的內容返回(err,data)
err 錯誤對象
data 讀取到的數據,會返回一個Buffer
步驟:
引入fs模塊
var fs = require('fs')
讀取
fs.readFile('gxb.jpg',function(err,data){
if(!err){
// console.log(data);
//將data寫入到文件中
fs.writeFile('hello.jpg',data,function(err){
if(!err){
console.log('文件寫入成功');
}
})
}
})
7.8. 流式文件讀取
流式文件讀取也適用于一些較大的文件,可以分多次將文件讀取到內存中
步驟1:
//引入fs模塊
var fs = require('fs')
//創建一個可讀流
var rs = fs.createReadStream('gxb.jpg')
//創建一個可寫流
var ws = fs.createWriteStream('hello2.jpg')
//監聽流的開啟和關閉
rs.once('open',function(){
console.log('可讀流打開了~~');
})
rs.once('close',function(){
console.log('可讀流關閉了~~');
//數據讀取完畢,關閉可寫流
ws.end()
})
ws.once('open',function(){
console.log('可寫流打開了~~');
})
ws.once('close',function(){
console.log('可寫流關閉了~~');
})
//如果要讀取一個可讀流中的數據,必須要為可讀流綁定一個data事件,
//data事件綁定完畢,它會自動開始讀取數據
//注意:流式文件讀取對象,并不是一次性讀取文件的全部數據,而是分多次讀取。
//所以,監聽data事件,就不能使用once,必須使用on
//once只監聽一次事件,on可以連續監聽。
rs.on('data',function(data){
// console.log(data);
// console.log(data.length);
// 將讀取到的數據寫入到可寫流中
ws.write(data)
})
步驟2:
//引入fs模塊
var fs = require('fs')
//創建一個可讀流
var rs = fs.createReadStream('gxb.jpg')
//創建一個可寫流
var ws = fs.createWriteStream('hello3.jpg')
//可以將可讀流中的內容,直接輸出到可寫流中
//相當于在這兩個對象之間建立的管道,可以直接傳輸數據。
rs.pipe(ws)
7.9. fs中其他方法
fs.existsSync(path)
- 檢查一個文件是否存在
fs.stat(path[, options], callback)
fs.statSync(path[, options])
- 獲取文件的狀態
- callback 回調函數,它會給我們返回一個對象,這個對象中保存了當前對象狀態的相關信息
fs.unlink(path, callback)
fs.unlinkSync(path)
- 刪除文件
fs.readdir(path[, options], callback)
fs.readdirSync(path[, options])
- 讀取一個目錄的目錄結構
- files 是一個字符串數組,每一個元素就是一個文件夾或文件的名字
fs.truncate(path[, len], callback)
fs.truncateSync(path[, len])
- 截斷文件,將文件修改為指定的大小
fs.mkdir(path[, options], callback)
fs.mkdirSync(path[, options])
- 創建一個目錄
fs.rmdir(path[, options], callback)
fs.rmdirSync(path[, options])
- 刪除一個目錄
fs.rename(oldPath, newPath, callback)
fs.renameSync(oldPath, newPath)
- 對文件進行重命名
- 參數
oldPath 舊的路徑
newPath 新的路徑
callback 回調函數
fs.watchFile(filename[, options], listener)
- 監視文件的修改
- 參數:
filename 要監視的文件的名字
options 配置選項
listener 回調函數,當文件發生變化時,回調函數會執行
在回調函數中會有兩個參數
curr 當前文件的狀態
prev 修改前文件的狀態
這兩個對象都是stats對象
7.10. 異步編程
7.10.1. 同步API, 異步API
同步API:只有當前API執行完成后,才能繼續執行下一個API
console.log('before');
console.log('after');
異步API:當前API的執行不會阻塞后續代碼的執行
console.log('before');
setTimeout(
() => { console.log('last');
}, 2000);
console.log('after');
7.10.2. 同步API, 異步API的區別( 獲取返回值 )
同步API可以從返回值中拿到API執行的結果, 但是異步API是不可以的
// 同步
function sum (n1, n2) {
return n1 + n2;
}
const result = sum (10, 20);
// 異步
function getMsg () {
setTimeout(function () {
return { msg: 'Hello Node.js' }
}, 2000);
}
const msg = getMsg ();
7.10.3. 回調函數
自己定義函數讓別人去調用。
// getData函數定義
function getData (callback) {}
// getData函數調用
getData (() => {});
使用回調函數獲取異步API執行結果
function getMsg (callback) {
setTimeout(function () {
callback ({ msg: 'Hello Node.js' })
}, 2000);
}
getMsg (function (msg) {
console.log(msg);
});
7.10.4. 同步API, 異步API的區別(代碼執行順序)
同步API從上到下依次執行,前面代碼會阻塞后面代碼的執行
for (var i = 0; i < 100000; i++) {
console.log(i);
}
console.log('for循環后面的代碼');
異步API不會等待API執行完成后再向下執行代碼
console.log('代碼開始執行');
setTimeout(() => { console.log('2秒后執行的代碼')}, 2000);
setTimeout(() => { console.log('"0秒"后執行的代碼')}, 0);
console.log('代碼結束執行');
7.10.5. Node.js中的異步API
fs.readFile('./demo.txt', (err, result) => {});
var server = http.createServer();
server.on('request', (req, res) => {});
如果異步API后面代碼的執行依賴當前異步API的執行結果,但實際上后續代碼在執行的時候異步API還沒有返回結果,這個問題要怎么解決呢?
fs.readFile('./demo.txt', (err, result) => {});
console.log('文件讀取結果');
需求:依次讀取A文件、B文件、C文件
7.10.6. Promise
Promise出現的目的是解決Node.js異步編程中回調地獄的問題。
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
if (true) {
resolve({name: '張三'})
}else {
reject('失敗了')
}
}, 2000);
});
promise.then(result => console.log(result); // {name: '張三'})
.catch(error => console.log(error); // 失敗了)
7.10.7. 異步函數
異步函數是異步編程語法的終極解決方案,它可以讓我們將異步代碼寫成同步的形式,讓代碼不再有回調函數嵌套,使代碼變得清晰明了。
const fn = async () => {};
async function fn () {}
async關鍵字
普通函數定義前加async關鍵字 普通函數變成異步函數
異步函數默認返回promise對象
在異步函數內部使用return關鍵字進行結果返回 結果會被包裹的promise對象中 return關鍵字代替了resolve方法
在異步函數內部使用throw關鍵字拋出程序異常
調用異步函數再鏈式調用then方法獲取異步函數執行結果
調用異步函數再鏈式調用catch方法獲取異步函數執行的錯誤信息
await關鍵字
await關鍵字只能出現在異步函數中
await promise await后面只能寫promise對象 寫其他類型的API是不不可以的
await關鍵字可是暫停異步函數向下執行 直到promise返回結果
8 MongoDB數據庫
8.1. 什么是數據庫
數據庫即存儲數據的倉庫,可以將數據進行有序的分門別類的存儲。它是獨立于語言之外的軟件,可以通過API去操作它。
常見的數據庫軟件有:mysql、mongoDB、oracle、sqlserver。
8.2. MongoDB數據庫下載安裝
下載地址:https://www.mongodb.com/try/download/community
MongoDB可視化軟件
下載地址:https://www.mongodb.com/try/download/compass
MongoDB數據庫工具
下載地址:https://www.mongodb.com/try/download/database-tools
8.3. 數據庫相關概念
在一個數據庫軟件中可以包含多個數據倉庫,在每個數據倉庫中可以包含多個數據集合,每個數據集合中可以包含多條文檔(具體的數據)。
術語解釋說明
database數據庫,mongoDB數據庫軟件中可以建立多個數據庫
collection集合,一組數據的集合,可以理解為JavaScript中的數組
document文檔,一條具體的數據,可以理解為JavaScript中的對象
field字段,文檔中的屬性名稱,可以理解為JavaScript中的對象屬性
8.4. Mongoose第三方包
使用Node.js操作MongoDB數據庫需要依賴Node.js第三方包mongoose
使用npm install mongoose命令下載
8.5. 啟動MongoDB
在命令行工具中運行net start mongoDB即可啟動MongoDB,否則MongoDB將無法連接。
8.5. 數據庫連接
使用mongoose提供的connect方法即可連接數據庫。
mongoose.connect('mongodb://localhost/playground',{ useNewUrlParser: true,useUnifiedTopology: true })
.then(() => console.log('數據庫連接成功'))
.catch(err => console.log('數據庫連接失敗', err));
8.6. 創建數據庫
在MongoDB中不需要顯式創建數據庫,如果正在使用的數據庫不存在,MongoDB會自動創建。
8.7. MongoDB增刪改查操作
8.7.1. 創建集合
創建集合分為兩步,一是對集合設定規則,二是創建集合,通過mongoose.Schema構造函數的實例即可創建集合。
// 設定集合規則
const courseSchema = new mongoose.Schema({
name: String,
author: String,
isPublished: Boolean
});
// 創建集合并應用規則
const Course = mongoose.model('Course', courseSchema); // courses
8.7.2. 創建文檔
創建文檔實際上就是向集合中插入數據。
分為兩步:
創建集合實例。
調用實例對象下的save方法將數據保存到數據庫中。
// 創建集合實例
const course = new Course({
name: 'Node.js course',
author: '兵哥',
tags: ['node', 'backend'],
isPublished: true
});
// 將數據保存到數據庫中
course.save(function(err,result){
// save方法,通過回調函數,返回添加的結果
if(!err){
console.log(result);
}
});
// 根據表對象,創建一個文檔對象,并將該文檔對象保存到數據庫的數據表中(回調函數方式)
Course.create({name: 'JavaScript基礎', author: '兵哥', isPublish: true}, (err, doc) => {
// 錯誤對象
console.log(err)
// 當前插入的文檔
console.log(doc)
});
//根據表對象,創建一個文檔對象,并將該文檔對象保存到數據庫的數據表中(Promise方式)
Course.create({name: 'JavaScript基礎', author: '兵哥', isPublish: true})
.then(doc => console.log(doc))
.catch(err => console.log(err))
8.7.3. mongoDB數據庫導入數據
mongoimport –d 數據庫名稱 –c 集合名稱 –file 要導入的數據文件
找到mongodb數據庫的安裝目錄,將安裝目錄下的bin目錄放置在環境變量中。
8.7.4. 查詢文檔
// 根據條件查找文檔(條件為空則查找所有文檔)
Course.find().then(result => console.log(result))
// 返回文檔集合
[{
_id: 5c0917ed37ec9b03c07cf95f,
name: 'node.js基礎',
author: '兵哥'
},{
_id: 5c09dea28acfb814980ff827,
name: 'Javascript',
author: '兵哥'
}]
// 根據條件查找文檔
Course.findOne({name: 'node.js基礎'}).then(result => console.log(result))
// 返回文檔
{
_id: 5c0917ed37ec9b03c07cf95f,
name: 'node.js基礎',
author: '兵哥'
}
// 匹配大于 小于
// age:{$lt:30,$gt:18} 不包括18和30
// age:{$lte:30,$gte:18} 包括18和30
User.find({age: {$gt: 20, $lt: 50}}).then(result => console.log(result))
// $regex用于設置正則表達式搜索
// 通過select方法,限定查詢哪些列,默認請情況_id都會返回,
// 如果不需要,通過-_id的方式去掉
User.find({name:{$regex:/劉/i}}).select('name sex age -_id').then(result=>{
console.log(result);
})
// 匹配包含
User.find({hobbies: {$in: ['敲代碼','學習']}}).then(result => console.log(result))
User.find({hobbies: {$all: ['敲代碼','學習']}}).then(result => console.log(result))
// 選擇要查詢的字段
User.find().select('name email').then(result => console.log(result))
// 將數據按照年齡進行排序
User.find().sort('age').then(result => console.log(result))
// 先根據性別升序,再根據年齡降序
User.find().sort('sex -age').then(result => console.log(result))
// skip 跳過多少條數據 limit 限制查詢數量
User.find().skip(2).limit(2).then(result => console.log(result))
8.7.5. 刪除文檔
// 刪除單個
Course.findOneAndDelete({}).then(result => console.log(result))
// 刪除多個
User.deleteMany({}).then(result => console.log(result))
8.7.6. 更新文檔
// 更新單個
User.updateOne({查詢條件}, {要修改的值}).then(result => console.log(result))
// 更新多個
User.updateMany({查詢條件}, {要更改的值}).then(result => console.log(result))
8.7.7. mongoose驗證
在創建集合規則時,可以設置當前字段的驗證規則,驗證失敗就輸入插入失敗。
required: true 必傳字段
minlength:3 字符串最小長度
maxlength: 20 字符串最大長度
min: 2 數值最小為2
max: 100 數值最大為100
enum: ['html', 'css', 'javascript', 'node.js']
trim: true 去除字符串兩邊的空格
validate: 自定義驗證器
default: 默認值
獲取錯誤信息:error.errors['字段名稱'].message
8.7.8. 集合關聯
通常不同集合的數據之間是有關系的,例如文章信息和用戶信息存儲在不同集合中,但文章是某個用戶發表的,要查詢文章的所有信息包括發表用戶,就需要用到集合關聯。
使用id對集合進行關聯
使用populate方法進行關聯集合查詢
// 用戶集合
const User = mongoose.model('User', new mongoose.Schema({ name: { type: String } }));
// 文章集合
const Post = mongoose.model('Post', new mongoose.Schema({
title: { type: String },
// 使用ID將文章集合和作者集合進行關聯
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
}));
//聯合查詢
Post.find()
.populate('author')
.then((err, result) => console.log(result));
9 Express框架
9.1. Express框架是什么
Express是一個基于Node平臺的web應用開發框架,它提供了一系列的強大特性,幫助你創建各種Web應用。
我們可以使用 npm install express 命令進行下載。
Express框架特性:
提供了方便簡潔的路由定義方式
對獲取HTTP請求參數進行了簡化處理
對模板引擎支持程度高,方便渲染動態HTML頁面
提供了中間件機制有效控制HTTP請求
擁有大量第三方中間件對功能進行擴展
9.2. 路由
// 當客戶端以get方式訪問/時
app.get('/', (req, res) => {
// 對客戶端做出響應
res.send('Hello Express');
});
// 當客戶端以post方式訪問/add路由時
app.post('/add', (req, res) => {
res.send('使用post方式請求了/add路由');
});
// 所有方式,優先級最高
app.all('/add',(req,res)=>{
res.send('使用get/post方式請求了/add路由');
})
9.3. 請求參數
app.get('/', (req, res) => {
// 獲取GET參數
console.log(req.query);
});
app.post('/', (req, res) => {
// 獲取POST參數
console.log(req.body);
})
9.4. Express初體驗
使用Express框架創建web服務器及其簡單,調用express模塊返回的函數即可。
// 引入Express框架
const express = require('express');
// 使用框架創建web服務器
const app = express();
// 當客戶端以get方式訪問/路由時
app.get('/', (req, res) => {
// 對客戶端做出響應 send方法會根據內容的類型自動設置請求頭
res.send('Hello Express'); //?<h2>Hello Express</h2>?{say: 'hello'}
});
// 程序監聽3000端口
app.listen(3000,()=>{console.log('服務已經啟動,端口號3000')});
9.5. 中間件
9.5.1. 什么是中間件
中間件就是一堆方法,可以接收客戶端發來的請求、可以對請求做出響應,也可以將請求繼續交給下一個中間件繼續處理。
中間件主要由兩部分構成,中間件方法以及請求處理函數。
中間件方法由Express提供,負責攔截請求,請求處理函數由開發人員提供,負責處理請求。
app.get('請求路徑', '處理函數') // 接收并處理get請求
app.post('請求路徑', '處理函數') // 接收并處理post請求
可以針對同一個請求設置多個中間件,對同一個請求進行多次處理。
默認情況下,請求從上到下依次匹配中間件,一旦匹配成功,終止匹配。
可以調用next方法將請求的控制權交給下一個中間件,直到遇到結束請求的中間件。
app.get('/request', (req, res, next) => {
req.name?= "張三";
next();
});
app.get('/request', (req, res) => {
res.send(req.name);
});
9.5.2. app.use中間件用法
app.use 匹配所有的請求方式,可以直接傳入請求處理函數,代表接收所有的請求。
app.use((req, res, next) => {
console.log(req.url);
next();
});
app.use 第一個參數也可以傳入請求地址,代表不論什么請求方式,只要是這個請求地址就接收這個請求。
app.use('/admin', (req, res, next) => {
console.log(req.url);
next();
});
9.5.3. 中間件應用
路由保護,客戶端在訪問需要登錄的頁面時,可以先使用中間件判斷用戶登錄狀態,用戶如果未登錄,則攔截請求,直接響應,禁止用戶進入需要登錄的頁面。
網站維護公告,在所有路由的最上面定義接收所有請求的中間件,直接為客戶端做出響應,網站正在維護中。
自定義404頁面。
9.5.4. 錯誤處理中間件
在程序執行的過程中,不可避免的會出現一些無法預料的錯誤,比如文件讀取失敗,數據庫連接失敗。
錯誤處理中間件是一個集中處理錯誤的地方。
app.use((err, req, res, next) => {
res.status(500).send('服務器發生未知錯誤');
})
當程序出現錯誤時,調用next()方法,并且將錯誤信息通過參數的形式傳遞給next()方法,即可觸發錯誤處理中間件。
app.get("/", (req, res, next) => {
fs.readFile("/file-does-not-exist", (err, data) => {
if (err) {
next(err);
}
});
});
9.5.5. 捕獲錯誤
在node.js中,異步API的錯誤信息都是通過回調函數獲取的,支持Promise對象的異步API發生錯誤可以通過catch方法捕獲。
異步函數執行如果發生錯誤要如何捕獲錯誤呢?
try catch 可以捕獲異步函數以及其他同步代碼在執行過程中發生的錯誤。
app.get("/", async (req, res, next) => {
try {
await User.find({name: '張三'})
}catch(ex) {
next(ex);
}
});
9.6. 構建模塊化路由
const express = require('express')
// 創建路由對象
const home = express.Router();
// 將路由和請求路徑進行匹配
app.use('/home', home);
// 在home路由下繼續創建路由
home.get('/index', () => {
// /home/index
res.send('歡迎來到博客展示頁面');
});
// home.js
const home = express.Router();
home.get('/index', () => {
res.send('歡迎來到博客展示頁面');
});
module.exports = home;
// admin.js
const admin = express.Router();
admin.get('/index', () => {
res.send('歡迎來到博客管理頁面');
});
module.exports = admin;
// app.js
const home = require('./route/home.js');
const admin = require('./route/admin.js');
app.use('/home', home);
app.use('/admin', admin);
9.7. 參數
9.7.1. GET參數的獲取
Express框架中使用req.query即可獲取GET參數,框架內部會將GET參數轉換為對象并返回。
// 接收地址欄中問號后面的參數
// 例如:?http://localhost:3000/?name=zhangsan&age=30
app.get('/', (req, res) => {
console.log(req.query); // {"name": "zhangsan", "age": "30"}
});
9.7.2. POST參數的獲取
舊版本的Express中接收post請求參數需要借助第三方包 body-parser。
// 引入body-parser模塊
const bodyParser = require('body-parser');
// 配置body-parser模塊
// 設置允許接收json格式的數據
app.use(bodyParser.json());
// 設置允許接收urlencoded格式的數據
app.use(bodyParser.urlencoded({ extended: false }));
新版本的Express不需要借助第三方包 body-parser
// 設置允許接收json格式的數據
app.use(express.json())
// 設置允許接收urlencoded格式的數據
app.use(express.urlencoded({extended:false}))
// 接收請求
app.post('/add', (req, res) => {
// 接收請求參數
console.log(req.body);
})
9.7.3. Express路由參數
app.get('/find/:id', (req, res) => {
console.log(req.params); // {id: 123}
});
localhost:3000/find/123
9.8. 靜態資源的處理
通過Express內置的express.static可以方便地托管靜態文件,例如img、CSS、JavaScript 文件等。
app.use(express.static('public'));
現在,public 目錄下面的文件就可以訪問了。
http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html
10 AJAX
10.1. HTTP
HTTP (hypertext transport protocol) 協議 [超文本傳輸協議],協議詳細規定了瀏覽器和萬維網之間相互通信的規則。
約定,規則。
10.1.1. 請求
重點是格式與參數
行 類型(GET POST) / URL / HTTP/1.1
頭 Host:?baidu.com
Cookie: name=汽車
Content-type: application/x-www-form-urlencoded
User-Agent: chrome 83
空行
體 username=admin&password=admin
10.1.2. 響應
行 HTTP/1.1 (200/404/403/401/500) OK
頭 Content-type: text/html;charset=utf-8
Content-length: 2048
Content-encoding: gzip
空行
體
<html><head></head><body><h1>Ajax</h1></body></html>
10.2. 同源策略
同源策略:是瀏覽器的一種安全策略。
同源:協議、域名、端口號 必須完全相同。
違背同源策略就是跨域。
如何解決跨域:
JSONP:是一個非官方的跨域解決方案,純粹憑借程序員的聰明才智開發出來的,只支持get請求。
JSONP 就是利用script標簽的跨域能力來發送請求的。
比如:img link iframe script。
CORS:跨域資源共享。是官方的跨域解決方案。
新增了一組HTTP首部字段,允許服務器聲明哪些源站通過瀏覽器有權限訪問哪些資源。
//設置響應頭 設置允許跨域
response.setHeader('Access-Control-Allow-Origin','*');
//響應頭 *表示所有類型的頭信息都可以接受
response.setHeader('Access-Control-Allow-Headers','*');
10.3. 原生AJAX
10.3.1. GET 請求
//1. 創建對象constxhr=newXMLHttpRequest();//2. 初始化 設置請求方法和URLxhr.open('GET','http://127.0.0.1:8000/server?a=100&b=200&c=300');//3. 發送xhr.send();//4. 事件綁定 處理服務端返回的結果// on? when? 當....時候// readystate 是 xhr 對象中的屬性,表示狀態 0 1 2 3 4// 0 表示未初始化// 1 表示open方法已經調用完畢// 2 表示send方法已經調用完畢// 3 表示服務端返回了部分的結果// 4 表示服務端返回了所有結果// change? 改變xhr.onreadystatechange=function(){//判斷(服務端返回了所有結果)if(xhr.readyState===4){//判斷響應狀態碼 200 404 403 401 500//2xx 成功if(xhr.status>=200&&xhr.status<300){//處理結果 行 頭 空行 體//1. 響應行console.log(xhr.status);//狀態碼console.log(xhr.statusText);//狀態字符串console.log(xhr.getAllResponseHeaders());//所有響應頭console.log(xhr.response);//響應體//設置 result 的文本result.innerHTML=xhr.response}else{}}}
10.3.2. POST 請求
//1. 創建對象constxhr=newXMLHttpRequest();//2. 初始化 設置類型與 URLxhr.open('POST','http://127.0.0.1:8000/server')//設置請求頭//Content-Type 是設置請求體內容的類型//application/x-www.form-urlencoded 是參數查詢字符串的類型//application/json 是json格式類型xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')//自定義頭xhr.setRequestHeader('name','bing')//3. 發送xhr.send('a=100&b=200&c=300')// xhr.send('a:100&b:200&c:300')//4. 事件綁定xhr.onreadystatechange=function(){//對狀態判斷if(xhr.readyState===4){if(xhr.status>=200&&xhr.status<300){//處理服務端返回的結果result.innerHTML=xhr.response}}}
10.3.3. 響應 JSON
//發送請求constxhr=newXMLHttpRequest();//設置響應體數據的類型xhr.responseType='json';//初始化xhr.open('GET','http://127.0.0.1:8000/json-server');//發送xhr.send()//事件綁定xhr.onreadystatechange=function(){if(xhr.readyState===4){if(xhr.status>=200&&xhr.status<300){// result.innerHTML = xhr.response//手動對數據轉換// let data = JSON.parse(xhr.response)// console.log(data);// result.innerHTML = data.name//自動轉換-->設置響應體數據的類型// console.log(xhr.response);result.innerHTML=xhr.response.name}}}
10.3.4. IE緩存問題
constxhr=newXMLHttpRequest();// url添加時間戳xhr.open('GET','http://127.0.0.1:8000/ie?t='+Date.now());xhr.send();xhr.onreadystatechange=function(){if(xhr.readyState===4){if(xhr.status>=200&&xhr.status<300){result.innerHTML=xhr.response}}}
10.3.5. 請求超時與網絡異常
constxhr=newXMLHttpRequest();//超時設置 2s 設置xhr.timeout=2000//超時回調xhr.ontimeout=function(){alert('網絡異常,請稍后重試!')}//網絡異常回調xhr.onerror=function(){alert('你的網絡似乎出了一些問題!')}xhr.open('GET','http://127.0.0.1:8000/delay');xhr.send();xhr.onreadystatechange=function(){if(xhr.readyState===4){if(xhr.status>=200&&xhr.status<300){result.innerHTML=xhr.response}}}
10.3.6. 取消請求
letxhr=newXMLHttpRequest();xhr.open('GET','http://127.0.0.1:8000/delay');//發送請求xhr.send()//取消請求xhr.abort()
10.3.7. 重復發送請求問題
//判斷標識變量if(isSending)x.abort();//如果正在發送,則取消該請求,創建一個新的請求x=newXMLHttpRequest();//修改 標識變量的值isSending=truex.open('GET','http://127.0.0.1:8000/delay');x.send()x.onreadystatechange=function(){if(x.readyState===4){//修改標識變量isSending=false}}
10.4. jQuery AJAX
<!-- crossorigin="anonymous" 跨語言的屬性設置 將不會攜帶該域名下的cookie --><scriptcrossorigin="anonymous"src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
10.4.1. GET方式
// 第四個參數:設置json。表示響應體是json對象
// 第四個參數:不設置。默認響應體是字符串
$.get('http://127.0.0.1:8000/jquery-server',{a:100,b:200},function(data){console.log(data);},'json')
10.4.2. POST方式
$.post('http://127.0.0.1:8000/jquery-server',{a:100,b:200},function(data){console.log(data);})
10.4.3. 通用型方法ajax
$.ajax({//url? ? ? ? url:'http://127.0.0.1:8000/jquery-server',//參數data:{a:100,b:200},//請求類型type:'GET',//響應體結果dataType:'json',//成功的回調success:function(data){console.log(data);},//超時時間timeout:2000,//失敗的回調error:function(){console.log('出錯啦!');},//頭信息headers:{c:300,d:400}})
10.5. axios
10.5.1. GET方式
axios.get('/axios-server',{//url 參數params:{id:100,vip:7},//請求頭信息headers:{name:'bing',age:20}}).then(value=>{console.log(value);})
10.5.2. POST方式
axios.post('/axios-server',{//請求體{username:'admin',password:'admin'},{//url 參數params:{id:200,vip:9},//請求頭參數headers:{height:180,weight:180}}).then(value=>{console.log(value);})
10.5.3. 通用方式
axios({//請求方法method:'POST',//urlurl:'/axios-server',//url參數params:{vip:10,level:30},//頭信息headers:{a:100,b:200},//請求體參數data:{username:'admin',password:'admin'}}).then(response=>{console.log(response);//響應狀態碼console.log(response.status);//響應狀態字符串console.log(response.statusText);//響應頭信息console.log(response.headers);//響應體console.log(response.data);})
10.6. fetch
fetch('http://127.0.0.1:8000/fetch-server?vip=10',{//請求方法method:'POST',//請求頭headers:{name:'bing'},//請求體body:'username=admin&password=admin'}).then(response=>{// console.log(response);// return response.text()returnresponse.json()}).then(response=>{console.log(response);})