隨着AJAX技術的誕生,前端正式進入了局部刷新和前后端分離的新時代,最初的服務請求技術是XHR,隨着技術發展和ES6的誕生,jquery ajax,axios,fetch 等技術的產生讓前端的異步請求更便捷.
當我們使用異步請求的時候可能會有中斷請求的需要.

比如當我們第一次查詢數據的時候沒有輸入查詢條件導致查詢很慢,於是我們第二次添加了查詢調價重新查詢很快結果返回並渲染到了頁面,
這時第一次的請求還在進行中,無法停止

當我們正在看數據的時候第一次的請求返回了結果並重新渲染了頁面,導致數據混亂
各種請求技術怎么又該怎么實現呢?下邊來分別進行簡述:
一、XHR
1.說明
AJAX 使用的 XMLHttpRequest 的對象與服務器通信.讓我們通過下面顯示的圖像了解 AJAX 的流程或 AJAX 的工作原理。

2.調用和中斷
const xhr = new XMLHttpRequest(); const method = 'GET'; const url = 'https://xxx'; xhr.open(method, url, true); xhr.onreadystatechange = () => { if (xhr.readyState === 4) { // do something } } xhr.send(); setTimeout(()=>{ xhr.abort()} ,1000)
jquery Ajax由於也是相同的
var ajaxGet = $.get(“https://xxx”,
{id:1},
function(data){undefined ….//一些操作 }
);
ajaxGet.abort();
二、axios
1.說明
眾所周知xhr技術雖然實現了異步調用但是如果連續有序地調用多個請求就會出現回調地獄的尷尬場面.
ES6推出的async/await promise可以很好的解決這個問題.而axios就是基於promise對xhr進行的封裝
核心代碼如下(簡單模擬非源碼):
1 function axios(config){ 2 return new Promise((resolve) => { 3 const {url='',data={},method='get'} = config; //解構傳參 4 const xhr = new XMLHttpRequest; //創建請求對象 5 xhr.open(method,url,true); 6 xhr.onreadystatechange = () => { 7 if(xhr.readyState == 4 && xhr.status == 200){ 8 resolve(xhr.responseText); 9 //異步請求返回后將Promise轉為成功態並將結果導出 10 } 11 } 12 xhr.onerror = (err) => { 13 reject(err); 14 }; 15 xhr.send(JSON.stringfy(data)); 16 }) 17 }
2.使用
// then catch 鏈式調用 axios.get('/user') .then(function (response) { console.log(response); axios.get('class?info=' + response.data.name); }) .catch(function (error) { console.log(error); }); // async await var info = await axios.get('user'); var ret = await axios.get('class?info=' + info.data.name);
3.中斷(取消)
axios 的中斷取消是基於 cancelable promises proposal
原理是內部生成一個Promise 將 resove 方法拋給外部的 source的cancel方法,
當外部調用這個方法時,內部的promise.then就會調用xhr.abort() 並調用外部的reject
可以使用 CancelToken.source 工廠方法創建 cancel token,像這樣:
const CancelToken = axios.CancelToken; const source = CancelToken.source(); axios.get('/user/12345', { cancelToken: source.token }).catch(function(thrown) { if (axios.isCancel(thrown)) {
// 取消處理 console.log('Request canceled', thrown.message); } else { // 處理錯誤 } }); axios.post('/user/12345', { name: 'new name' }, { cancelToken: source.token }) // 取消請求(message 參數是可選的) source.cancel('Operation canceled by the user.');
還可以通過傳遞一個 executor 函數到 CancelToken 的構造函數來創建 cancel token:
const CancelToken = axios.CancelToken; let cancel; axios.get('/user/12345', { cancelToken: new CancelToken(function executor(c) { // executor 函數接收一個 cancel 函數作為參數 cancel = c; }) }); // cancel the request cancel();
三、Fetch
1.說明
Fetch也是基於ES6 Promise 實現的一個服務器請求技術,但不是對xhr的封裝.
也是底層的實現不需要引入包,是 XMLHttpRequest 的升級版.兼容除了IE的大部分瀏覽器
2.基本使用
// then catch 鏈式調用
fetch('https://xxxx').then(response => response.json()).then(json => console.log(json)).catch(err => console.log('Request Failed', err));async function getJSON() {
// async await
let url = 'https:XXXX';
try {
let response = await fetch(url);
return await response.json();
} catch (error) {
console.log('Request Failed', error);
}
}
3.中斷
Fetch的中斷是基於webApi的 AbortController(實驗階段的功能兼容除了IE的大部分瀏覽器)
var controller = new AbortController(); var signal = controller.signal; // 可以監聽取消事件 signal.addEventListener('abort', () => console.log('abort!') ); setTimeout(()=>{ //定時或者手動調用abort方法中斷 controller.abort(); },1000) fetch('http://xxxx', {signal}).then(function(response) { ... }).catch(function(e) { if(signal.aborted){ // 可以通過 signal.aborted 屬性判斷 ... } if(e.name=='AbortError'){ // 也可以通過 error.name 判斷 ... } })/
四 、其他實現方法
其實在知道這些中斷方法之前本人還用過其他的方法——uuid
主要思路就是每次調用請求的時候生成一個uuid,將這個uuid賦值給全局的變量同時作為參數傳給請求的方法.
在請求返回處理數據的時候驗證當前的全局uuid 是否和當前調用參數是否一致,不一致就不渲染數據,
這樣就能保證渲染的數據是最后一次調用請求的數據
//以Fetch為例 this.uuid = "" // 自己寫一個生成uuid的方法,或者使用第三方的包 function genUUID(){ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = (Math.random() * 16) | 0 var v = c === 'x' ? r : (r & 0x3) | 0x8 return v.toString(16) }) } function fetchData(){ // 賦值給局部變量和全局變量 let uuid = genUUID() this.uuid = uuid fetch(url).then(res=>{ if(this.uuid === uuid){ // 渲染數據 } }) }
參考鏈接:
https://www.w3cschool.cn/ajax/ajax-tutorial.html
https://www.cnblogs.com/ysk123/p/11544211.html
