AJAX學習筆記
- 一、什麼是AJAX?
-
- 1.原生AJAX
- 2.XML
- 3.AJAX的優缺點
- 二、HTTP協定
-
- 1.請求封包
- 2.響應封包
- 三、AJAX案例準備工作
-
- 1.安裝express
- 2.建立一個服務端
- 3.nodemon實作儲存自動重新開機服務
- 四、發送AJAX請求
-
- 1.發送GET請求
- 2.發送POST請求
- 3.JSON響應
-
- (1)手動把JSON字元串轉換為js對象
- (2)自動把JSON字元串轉換為js對象
- 五、AJAX請求的幾個問題
-
- 1.IE緩存問題
- 2.AJAX請求逾時與網絡異常處理
- 3.AJAX手動取消請求
- 4.AJAX請求重複發送問題
一、什麼是AJAX?
1.原生AJAX
AJAX 全稱為Asynchronous Javascript And XML。就是異步的JS和XML。通過AJAX 可以在浏覽器中向伺服器發送異步請求,最大的優勢:無重新整理擷取資料。AJAX 不是新的程式設計語言,而是一種将現有的标準組合在一起使用的新方式。
2.XML
可擴充标記語言。XML被設計用來傳輸和存儲資料。XML和HTML類似,不同的是HTML中都是預定義标簽,而XML中沒有預定義标簽,全部都是自定義标簽,用來表示一些資料。(目前已經被JSON取代)
3.AJAX的優缺點
優點:
(1)可以無需重新整理頁面而與伺服器端進行通信。
(2)允許你根據使用者事件來更新部分頁面内容。
缺點:
(1)沒有浏覽曆史,不能回退。
(2)存在跨域問題(同源)
(3)SEO不友好(檢視源代碼中無法查找到)
二、HTTP協定
HTTP全稱為hypertext transport protocol 協定【超文本傳輸協定】,協定詳細規定了浏覽器和網際網路伺服器之間互相通信的規則。
重點格式與參數:
1.請求封包
行:
POST
/URL HTTP
協定版本
頭:
Host:值
Cookie: 值
Content-type:值
User-Agent:值
等等
空行:
體:如果是GET請求體為空,如果是POST可以不為空
2.響應封包
行:
HTTP協定版本
響應狀态碼
響應狀态字元串
頭:
Content-type:值
Content-length:值
Content-encoding:值
等等
空行:
體:HTML文法内容
三、AJAX案例準備工作
1.安裝express
之前腳手架的時候配置過node環境,是以這裡的安裝非常順利,沒有任何報錯。隻需要在vscode => 終端 => 目前目錄中 => 輸入
npm i express
就歐了。如果出錯了去翻我的配置Vue腳手架筆記。
其實這裡也可以安裝到全局,也就是安到node.js的根目錄裡,好像是
npm i express -g
2.建立一個服務端
在目前目錄建立個js檔案(不一定非要在express安裝的根目錄噢),然後在終端 => 目前目錄下 => 輸入
node 檔案名
就可以啟動服務
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLjdzM2cDO2AjZ3Y2MzcTYhFWN5QDO4ATZ2ITY2EmY2kzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
//1.引入express
const express = require('express');
//2.建立應用對象
const app = express();
//3.建立路由規則
//request是對請求封包的封裝
//response是對響應封包的封裝
app.get('/', (request, response) => {
//設定響應
response.send('HELLO EXPRESS');
})
//4.監聽端口啟動服務
app.listen(8000, () => {
console.log('服務已經啟動,8000端口監聽中...');
})
網頁打開:
端口釋放:Ctrl+c
3.nodemon實作儲存自動重新開機服務
終端運作
npm install -g nodemon
安裝nodemon,這樣每次儲存就會自動重新開機服務,比較友善(副作用是所有html都無法儲存時自動調整格式),使用時還是在目前目錄
nodemon+檔案名
,如
nodemon server.js
(之前是
node server.js
)
四、發送AJAX請求
1.發送GET請求
點選按鈕div中呈現響應體:點選按鈕發送AJAX請求給伺服器,然後把響應體拿過來放到div中。
沒見過這些東西,照着敲的,仔細看我寫的注釋
<button>點選發送請求</button>
<div id="result"></div>
//擷取button元素
const btn = document.querySelector('button');
const result = document.querySelector('#result');
btn.addEventListener('click', function() {
//1.建立對象
const xhr = new XMLHttpRequest();
//2.初始化,設定請求的方法和url
xhr.open('GET','http://127.0.0.1:8000/server?a=1&b=2&c=3');
//3.發送
xhr.send();
//4.事件綁定,處理服務端傳回的結果
//on 當……的時候
//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 ,2開頭都表示成功
if(xhr.status >= 200 && xhr.status < 300){
//如果響應成功處理結果 行 頭 空行 體
console.log('狀态碼:',xhr.status); //狀态碼
console.log('狀态字元串:',xhr.statusText); //狀态字元串
console.log('響應頭:',xhr.getAllResponseHeaders()); //所有的響應頭
console.log('響應體:',xhr.response); //響應體
//設定result文本
result.innerHTML = xhr.response;
}
}
}
})
設定url參數:
用?隔開,=指派,&分隔
例如:
http://127.0.0.1:8000/server?a=1&b=2&c=3
看不懂的服務端server.js檔案:
//1.引入express
const express = require('express');
//2.建立應用對象
const app = express();
//3.建立路由規則
//request是對請求封包的封裝
//response是對響應封包的封裝
app.get('/server', (request, response) => {
//設定響應頭
response.setHeader('Access-Control-Allow-Origin', '*');
//設定響應體
response.send('HELLO AJAX');
})
//4.監聽端口啟動服務
app.listen(8000, () => {
console.log('服務已經啟動,8000端口監聽中...');
})
2.發送POST請求
滑鼠經過div發送AJAX請求,然後拿回來響應體放在div中
仔細對比GET和POST的不同,好像這個傳參在send中寫,類型随便??
還有就是可以
xhr.setRequestHeader
設定請求頭,仔細看看注釋
const result = document.querySelector('#result');
result.addEventListener('mouseover' ,function() {
//1.建立對象
const xhr = new XMLHttpRequest();
//2.初始化 設定類型與url
xhr.open('POST','http://127.0.0.1:8000/server');
//設定請求頭:固定寫法,第一個參數設定請求體内容類型,第二個參數是參數查詢字元串的類型
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
//3.發送請求,在這裡傳參,任意類型都歐
xhr.send('a=1&b=2&c=3');
// xhr.send('a:1&b:2&c:3');
// xhr.send('1232142412421312');
//4.綁定事件
xhr.onreadystatechange = function() {
//判斷服務端是否傳回所有結果
if(xhr.readyState === 4) {
//判斷響應是否成功
if(xhr.status >=200 && xhr.status<300) {
//處理服務端傳回的結果
result.innerHTML = xhr.response;
}
}
}
})
server.js
//1.引入express
const express = require('express');
//2.建立應用對象
const app = express();
//3.建立路由規則
//request是對請求封包的封裝
//response是對響應封包的封裝
//POST請求
app.post('/server', (request, response) => {
//設定響應頭
response.setHeader('Access-Control-Allow-Origin', '*');
//設定響應體
response.send('HELLO AJAX POST');
})
//4.監聽端口啟動服務
app.listen(8000, () => {
console.log('服務已經啟動,8000端口監聽中...');
})
3.JSON響應
服務端響應體也可以設定為一個資料發送過去,但是不能直接寫,要通過
JSON.stringify(資料)
把資料轉換為JSON字元串
app.get('/json-server', (request, response) => {
//設定響應頭
response.setHeader('Access-Control-Allow-Origin', '*');
//響應一個資料
const data = { name: 'ht' };
let str = JSON.stringify(data); //對對象進行字元串轉換
//設定響應體
response.send(str);
})
頁面在拿到JSON字元串響應體的時候,是無法識别的,是以需要把JSON字元串轉換為js對象,有兩種方式:
(1)手動把JSON字元串轉換為js對象
借助
JSON.parse(xhr.response)
let data = JSON.parse(xhr.response);
console.log(data); //js對象:{ name: 'ht' }
result.innerHTML = data.name;
(2)自動把JSON字元串轉換為js對象
借助
xhr.responseType = 'json';
xhr.responseType = 'json';
......
console.log(xhr.response); //js對象:{ name: 'ht' }
result.innerHTML = xhr.response.name;
五、AJAX請求的幾個問題
1.IE緩存問題
//IE緩存問題
app.get('/ie', (request, response) => {
//設定響應頭
response.setHeader('Access-Control-Allow-Origin', '*');
//設定響應體
response.send('HELLO IE 666');
})
惡心的IE當你響應體改變時,它不會更新,而是走緩存,想要解決這個問題,就要讓每次請求的url都不一樣,那麼我們在後面傳個參數,值為時間戳,就可以解決改變響應體時IE走緩存不更新的問題
2.AJAX請求逾時與網絡異常處理
服務端寫個定時器,2秒後發送響應體過去
app.get('/delay', (request, response) => {
//設定響應頭
response.setHeader('Access-Control-Allow-Origin', '*');
//設定響應體
setTimeout(() => {
response.send('HELLO 我延遲響應啦');
}, 2000);
})
然後點選按鈕發送請求時,可以設定逾時
xhr.timeout
和逾時回調
xhr.ontimeout
,還有網絡異常回調
xhr.onerror
const xhr = new XMLHttpRequest();
//逾時設定,1s還沒收到響應體,就取消請求
xhr.timeout = 1000;
//逾時回調
xhr.ontimeout = function() {
alert('請求逾時baby!');
}
//網絡異常回調
xhr.onerror = function () {
alert('你的網絡似乎開小差了!!');
}
Chorme浏覽器可以手動斷網
3.AJAX手動取消請求
還是搞個定時器發送響應體
app.get('/cancel', (request, response) => {
//設定響應頭
response.setHeader('Access-Control-Allow-Origin', '*');
//設定響應體
setTimeout(() => {
response.send('HELLO 我請求被取消了,沒法發過去了');
}, 2000);
})
整倆按鈕
<button>點選發送請求</button>
<button>點選取消請求</button>
取消請求,用
xhr.abort()
方法,abort中文意思是中止
這裡邊兒有個作用域的問題,解決方法是把xhr定義在外邊給個null,然後指派xhr執行個體,再調用方法。(重複指派不要用const噢,能用const就用const,不能const就let,反正别var揍中了)
const send = document.querySelectorAll('button')[0];
const cancel = document.querySelectorAll('button')[1];
let xhr = null;
//發送請求
send.onclick = function() {
xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8000/cancel');
xhr.send(); //不用拿響應體,是以後邊兒不寫了
}
//取消請求,abort方法
cancel.addEventListener('click', function() {
xhr.abort(); //先點send再點cancel不會報錯,先點cancel報錯
console.log(xhr); //先點send再點cancel是xhr執行個體,先點cancel報錯
})
4.AJAX請求重複發送問題
服務端還是用的前面的定時器,這裡重複請求寫個邏輯,如果沒處在請求中,就建立新的請求;如果已經請求了,就廢掉,再重新建立請求。具體看代碼和注釋吧,這塊兒聽的不是很清晰,先簡單了解下,還有啊,作用域回頭得補補,這塊兒太不熟了
const send = document.querySelector('button');
let xhr = null;
let isSending = false; //是否正在發送AJAX請求
//發送請求
send.onclick = function() {
//如果沒處在請求中,就建立新的請求;如果已經請求了,就廢掉,再重新建立請求
if(isSending) xhr.abort();
xhr = new XMLHttpRequest();
isSending = true;
xhr.open('GET', 'http://127.0.0.1:8000/delay');
xhr.send();
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
//有可能請求失敗,是以這裡不用再做判斷,隻要拿到結果,就算請求完成
isSending = false; //拿到伺服器的全部結果後,置為false
}
}
}