2019-10-29 seo達人
1, JavaScript的Ajax
Ajax的全稱是Asynchronous JavaScript and XML,意思就是用JavaScript執行異步網絡請求,而不需要重載(刷新)整個頁面。
Ajax使用XMLHttpRequest對象取得新數據,然后再通過 DOM 將新數據插入到頁面中。另外,雖然名字中包含 XML 的成分,但 Ajax 通信與數據格式無關; 這種技術就是無須刷新頁面即可從服務器取得數據,但不一定是 XML 數據。
對于IE7+和其他瀏覽器,可以直接使用XMLHttpRequest對象,對于IE6及以前的瀏覽器,使用ActiveXObject對象。
使用方法如下:
var xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
1
2
3
4
5
6
啟動請求:
xhr.open(method, url, boolean);
xhr.send();
1
2
注:
1,xhr.open參數含義:
method:請求方式,post、get等
url: 請求鏈接,只能向同源的url發送請求
boolean:是否異步請求,true:異步, false: 同步,默認為true
2,調用 open()方法并不會真正發送請求, 而只是啟動一個請求以備發送。
3,send()方法接收一個參數,即要作為請求主體發送的數據(post方法會使用,get方法直接傳null)。如果不需要通過請求主體發送數據,則必須傳入 null,因為這個參數對有些瀏覽器來說是必需的。調用send()之后,請求就會被分派到服務器。
XMLHttpRequest對象的異步請求示例如下:
function success(text) {
console.log(text);
}
function fail(code) {
console.log(code);
}
var xhr = new XMLHttpRequest(); // 新建XMLHttpRequest對象
xhr.onreadystatechange = function () {
// 狀態發生變化時,函數被回調
if (xhr.readyState === 4) { // 成功完成
// 判斷響應結果:
if (xhr.status === 200) {
// 成功,通過responseText拿到響應的文本:
return success(xhr.responseText);
} else {
// 失敗,根據響應碼判斷失敗原因:
return fail(xhr.status);
}
} else {
// HTTP請求還在繼續...
}
}
// 發送請求:
xhr.open('get', '/api/categories');
xhr.send(null);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
xhr的屬性含義如下:
responseText: 作為響應主體被返回的文本。
responseXML: 如果響應的內容類型是"text/xml"或"application/xml",這個屬性中將保存響應數據的 XML DOM 文檔。
status: 響應的 HTTP 狀態。
statusText: HTTP 狀態的說明。
readyState :表示請求/響應過程的當前活動階段??扇≈等缦隆?br />
0: 未初始化。尚未調用 open()方法。
1: 啟動。已經調用 open()方法,但尚未調用 send()方法。
2: 發送。已經調用 send()方法,但尚未接收到響應。
3: 接收。已經接收到部分響應數據。
4: 完成。已經接收到全部響應數據,而且已經可以在客戶端使用了。
只要 readyState 屬性的值由一個值變成另一個值,都會觸發一次 readystatechange 事件。可以利用這個事件來檢測每次狀態變化后readyState 的值。通常,我們只對 readyState 值為 4 的階段感興趣,因為這時所有數據都已經就緒。不過,必須在調用 open()之前指定 onreadystatechange事件處理程序才能確??鐬g覽器兼容性。
另外,在接收到響應之前還可以調用 abort()方法來取消異步請求:
xhr.abort();
1
調用這個方法后,XHR 對象會停止觸發事件,而且也不再允許訪問任何與響應有關的對象屬性。在終止請求之后,還應該對 XHR 對象進行解引用操作。由于內存原因,不建議重用 XHR 對象。
2, jQuery的Ajax
$.ajax({
url:"",
type:"GET",
contentType: '',
async:true,
data:{},
dataType:"",
success: function(){
}
});
1
2
3
4
5
6
7
8
9
10
url 必填項,規定把請求發送到哪個 URL。
type 以什么樣的方式獲取數據,是get或post
contentType:發送POST請求的格式,默認值為’application/x-www-form-urlencoded;
charset=UTF-8’,也可以指定為text/plain、application/json
async 是否異步執行AJAX請求,默認為true,千萬不要指定為false
data 發送的數據,可以是字符串、數組或object。如果是GET請求,data將被轉換成query附加到URL上,如果是POST請求,根據contentType把data序列化成合適的格式;
dataType
接收的數據格式,可以指定為’html’、‘xml’、‘json’、'text’等,缺省情況下根據響應的Content-Type猜測。
success 可選。執行成功時返回的數據。
缺點:
是基于XHR原生開發的,目前已有的fetch可替代。本身是針對mvc的編程模式,不太適合目前mvvm的編程模式。jQuery本身比較大,如果單純的使用ajax可以自己封裝一個,不然會影響性能體驗。
3,Axios
Vue2.0之后,axios開始受到更多的歡迎。其實axios也是對原生XHR的一種封裝,不過是Promise實現版本。它是一個用于瀏覽器和 nodejs 的 HTTP 客戶端,符合的ES規范。
axios具有以下特征:
從瀏覽器中創建 XMLHttpRequest
支持 Promise API
客戶端支持防止CSRF
提供了一些并發請求的接口
從 node.js 創建 http 請求
攔截請求和響應
轉換請求和響應數據
取消請求
自動轉換JSON數據
PS:防止CSRF:就是讓你的每個請求都帶一個從cookie中拿到的key, 根據瀏覽器同源策略,假冒的網站是拿不到你cookie中得key的,這樣,后臺就可以輕松辨別出這個請求是否是用戶在假冒網站上的誤導輸入,從而采取正確的策略。
設置全局的 axios 默認值
axios.defaults.baseURL = '
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
1
2
3
注:axios 的 headers的 content-type 默認是 “application/json ”
默認情況下,axios將JavaScript對象序列化為JSON,如果是get請求,對請求參數不用做任何處理,但是如果是post請求,并且Content-Type 為application/x-www-form-urlencoded,需要使用URLSearchParams API格式化請求參數, 否則Content-Type依然是application/json
var params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
1
2
3
get請求,以下3中寫法完全等價
axios.get('/user?id=12345&name=xiaoming')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
1
2
3
4
5
6
7
axios.get('/user', {
params: {
id: '12345',
name: 'xiaoming'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
1
2
3
4
5
6
7
8
9
10
11
12
axios({
url: '/user',
method: 'get',
params: {
id: '12345',
name: 'xiaoming'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
post請求,以下2種寫法完全等價
axios({
url: '/user',
method: 'post',
headers: {
'Content-Type': 'application/json'
},
data: {
id: '12345',
name: 'xiaoming'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var url = '/user';
var data = {
id: '12345',
name: 'xiaoming'
};
axios.post(url, data, {
headers: {
'Content-Type': 'application/json'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
執行多個并發請求
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// 兩個請求現在都執行完成
}));
1
2
3
4
5
6
7
8
9
10
11
12
創建實例
可以使用自定義配置新建一個 axios 實例
axios.create([config])
var instance = axios.create({
baseURL: '
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
1
2
3
4
5
6
配置會以一個優先順序進行合并,順序由低到高為
1,在 node_modules/axios/lib/defaults.js 找到的庫的默認值
2,實例的 defaults 屬性
3,請求的 config 參數
// 使用由庫提供的配置的默認值來創建實例
// 此時超時配置的默認值是 0
var instance = axios.create();
// 覆寫庫的超時默認值
// 現在,所有請求都會等待 2.5 秒
instance.defaults.timeout = 2500;
// 為已知需要花費很長時間的請求覆寫超時設置
instance.get('/longRequest', {
timeout: 5000
});
1
2
3
4
5
6
7
8
9
10
11
12
攔截器
在請求發出之前或響應被 then 或 catch 處理前攔截它們做預處理。
// 添加請求攔截器
axios.interceptors.request.use(function (config) {
// 在發送請求之前做些什么
}, function (error) {
// 對請求錯誤做些什么
});
// 添加響應攔截器
axios.interceptors.response.use(function (response) {
// 對響應數據做點什么
}, function (error) {
// 對響應錯誤做點什么
});
1
2
3
4
5
6
7
8
9
10
11
12
13
可以在稍后移除攔截器:
var myInterceptor = axios.interceptors.request.use(function () {/.../});
axios.interceptors.request.eject(myInterceptor);
1
2
可以為自定義 axios 實例添加攔截器
var instance = axios.create();
instance.interceptors.request.use(function () {/.../});
1
2
4, fetch
window 自帶了 window.fetch 方法, 在版的 Firefox 和 Chrome 中已經提供支持,其他瀏覽器還有兼容性問題,要做兼容性處理。fetch 是一個 基于promise設計的low-level API,不是ajax的進一步封裝,而是原生js,它注定不會像你習慣的 $.ajax 或是 axios 等庫幫你封裝各種各樣的功能或實現.
interface GlobalFetch {
fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
}
1
2
3
fetch()是一個全局的函數,返回一個promise對象。它有兩個參數,第一個參數是請求的地址,第二個參數是可選,RequestInit是個對象格式如下:
interface RequestInit {
body?: any;
cache?: RequestCache;
credentials?: RequestCredentials;
headers?: HeadersInit;
integrity?: string;
keepalive?: boolean;
method?: string;
mode?: RequestMode;
redirect?: RequestRedirect;
referrer?: string;
referrerPolicy?: ReferrerPolicy;
window?: any;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
優點:
符合關注分離,沒有將輸入、輸出和用事件來跟蹤的狀態混雜在一個對象里
更好更方便的寫法
更加底層,提供的API豐富
脫離了XHR,是ES規范里新的實現方式
fetch中可以設置mode為"no-cors"(不跨域)
缺點:
fetch不支持同步請求
fetch只對網絡請求報錯,對400,500都當做成功的請求,需要封裝去處理
fetch默認不會帶cookie,需要添加配置項
fetch不支持abort,不支持超時控制,使用setTimeout及Promise.reject的實現的超時控制并不能阻止請求過程繼續在后臺運行,造成了流量的浪費
fetch沒有辦法原生監測請求的進度,而XHR可以
fetch的使用示例:
window.fetch(url)
.then(response => {
if (response.ok) {
//通過 response 原型上的 json 方法將 response.body 轉換為 JS 對象,再返回出去
return response.json();
}
}
).then(result => {
console.log(result);
}).catch(error => {
console.log(error);
})
1
2
3
4
5
6
7
8
9
10
11
12
需要注意以下幾點:
1,用 response.ok判斷fetch請求是否成功
2,服務端只返回了response對象,而真正的請求結果,即 response.body,則是一個 ReadableStream。fetch 將 response.body 設計成 ReadableStream 在請求大體積文件時變得非常有用。然而,在我們的日常使用中,還是短小的 JSON 片段更加常見。而為了兼容不常見的設計,我們不得不多一次 response.json() 的調用。不僅是調用變得麻煩,如果你的服務端采用了嚴格的 REST 風格,對于某些特殊情況并沒有返回 JSON 字符串,而是用了 HTTP 狀態碼(如:204 No Content),那么在調用 response.json() 時則會拋出異常。
3,Response 限制了響應內容的重復讀取和轉換,response .json / response.text 方法只能使用一個并且只能使用一次,同時使用兩個,或使用兩次都會報如下錯誤:
Uncaught (in promise) TypeError: Failed to execute 'json' on 'Response': body stream is locked
1
為什么不能使用兩次?
因為數據流只能讀取一次,一旦讀取,數據流變空,再次讀取會報錯。
————————————————
版權聲明:本文為CSDN博主「Sherry慈」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_41480546/article/details/102805864