網(wǎng)站首頁 編程語言 正文
AJAX原理
- Ajax的原理簡單來說是在用戶和服務(wù)器之間加了—個中間層(AJAX引擎),通過XmlHttpRequest對象來向服務(wù)器發(fā)異步請求,從服務(wù)器獲得數(shù)據(jù),然后用javascript來操作DOM而更新頁面。使用戶操作與服務(wù)器響應(yīng)異步化。
- Ajax的過程只涉及JavaScript、XMLHttpRequest和DOM。XMLHttpRequest是ajax的核心機(jī)制
XMLHttpRequest(XHR)對象用于與服務(wù)器交互。通過 XMLHttpRequest 可以在不刷新頁面的情況下請求特定 URL,獲取數(shù)據(jù)。這允許網(wǎng)頁在不影響用戶操作的情況下,更新頁面的局部內(nèi)容。XMLHttpRequest 可以用于獲取任何類型的數(shù)據(jù),而不僅僅是 XML。甚至支持 HTTP以外的協(xié)議(包括 file:// 和 FTP),盡管可能受到更多出于安全等原因的限制。
/** 1. 創(chuàng)建Ajax對象 **/ var xhr = window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP');// 兼容IE6及以下版本 /** 2. 配置 Ajax請求 **/ xhr.open('get', url, true) /** 3. 發(fā)送請求 **/ xhr.send(null); // 嚴(yán)謹(jǐn)寫法 /** 4. 監(jiān)聽請求,接受響應(yīng) **/ xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ if(xhr.status == 200){ success(xhr.responseText); } else { /** false **/ fail && fail(xhr.status); } } }
onreadystatechange:當(dāng) readyState 屬性發(fā)生變化時,調(diào)用的事件處理函數(shù)
-
readyState:
值 狀態(tài) 描述 0 UNSENT 代理被創(chuàng)建,但尚未調(diào)用 open() 方法。 1 OPENED open() 方法已經(jīng)被調(diào)用。 2 HEADERS_RECEIVED send() 方法已經(jīng)被調(diào)用,并且頭部和狀態(tài)已經(jīng)可獲得。 3 LOADING 下載中; responseText 屬性已經(jīng)包含部分?jǐn)?shù)據(jù)。 4 DONE 下載操作已完成。 response:返回的包含整個響應(yīng)實體
responseText:返回一個DOMString,該 DOMString 包含對請求的響應(yīng),如果請求未成功或尚未發(fā)送,則返回 null。
-
responseType:一個用于定義響應(yīng)類型的枚舉值(enumerated value)。
類型 解釋 “ ” 空的 responseType 字符串與默認(rèn)類型 "text" 相同。 "arraybuffer" response 是一個包含二進(jìn)制數(shù)據(jù)的 JavaScript ArrayBuffer。 "blob" response 是一個包含二進(jìn)制數(shù)據(jù)的 Blob 對象。 "document" response 是一個 HTMLDocument或XMLDocument "json" response是通過將接收到的數(shù)據(jù)內(nèi)容解析為JSON的JS對象 "text" response 是 DOMString 對象中的文本。 "ms-stream" response是流式下載的一部分;此響應(yīng)類型僅允許用于下載請求,并且僅受 Internet Explorer 支持。 -
status:返回一個無符號短整型(unsigned short)數(shù)字,代表請求的響應(yīng)狀態(tài)。
var xhr = new XMLHttpRequest(); console.log('UNSENT', xhr.status); xhr.open('GET', '/server', true); console.log('OPENED', xhr.status); xhr.onprogress = function () { console.log('LOADING', xhr.status); }; xhr.onload = function () { console.log('DONE', xhr.status); }; xhr.send(null); /** * 輸出如下: * * UNSENT(未發(fā)送) 0 * OPENED(已打開) 0 * LOADING(載入中) 200 * DONE(完成) 200 */
withCredentials:一個布爾值,用來指定跨域 Access-Control 請求是否應(yīng)當(dāng)帶有授權(quán)信息,如 cookie 或授權(quán) header 頭。
xhr.withCredentials=true
upload:代表上傳進(jìn)度
其他更多XMLHttpRequest相關(guān)api
ajax 有那些優(yōu)缺點(diǎn)?
-
優(yōu)點(diǎn):
- 通過異步模式,提升了用戶體驗.
- 優(yōu)化了瀏覽器和服務(wù)器之間的傳輸,減少不必要的數(shù)據(jù)往返,減少了帶寬占用.
- Ajax在客戶端運(yùn)行,承擔(dān)了一部分本來由服務(wù)器承擔(dān)的工作,減少了大用戶量下的服務(wù)器負(fù)載。
- Ajax可以實現(xiàn)動態(tài)不刷新(局部刷新)
-
缺點(diǎn):
- 安全問題 AJAX暴露了與服務(wù)器交互的細(xì)節(jié)。
- 對搜索引擎的支持比較弱。
- 不容易調(diào)試。
Promise封裝Ajax
promise 封裝實現(xiàn):
// promise 封裝實現(xiàn): function getJSON(url) { // 創(chuàng)建一個 promise 對象 let promise = new Promise(function(resolve, reject) { let xhr = new XMLHttpRequest(); // 新建一個 http 請求 xhr.open("GET", url, true); // 設(shè)置狀態(tài)的監(jiān)聽函數(shù) xhr.onreadystatechange = function() { if (this.readyState !== 4) return; // 當(dāng)請求成功或失敗時,改變 promise 的狀態(tài) if (this.status === 200) { resolve(this.response); } else { reject(new Error(this.statusText)); } }; // 設(shè)置錯誤監(jiān)聽函數(shù) xhr.onerror = function() { reject(new Error(this.statusText)); }; // 設(shè)置響應(yīng)的數(shù)據(jù)類型 xhr.responseType = "json"; // 設(shè)置請求頭信息 xhr.setRequestHeader("Accept", "application/json"); // 發(fā)送 http 請求 xhr.send(null); }); return promise; }
JQ Ajax、Axios、Fetch的核心區(qū)別
JQuery Ajax
Ajax前后端數(shù)據(jù)通信「同源、跨域」
// 用戶登錄 -> 登錄成功 -> 獲取用戶信息 /* 回調(diào)地獄 */ $.ajax({ url: 'http://127.0.0.1:8888/user/login', method: 'post', data: Qs.stringify({ account: '18310612838', password: md5('1234567890') }), success(result) { if (result.code === 0) { // 登錄成功 $.ajax({ url: 'http://127.0.0.1:8888/user/list', method: 'get', success(result) { console.log(result); } }); } } });
優(yōu)缺點(diǎn):
- 本身是針對MVC的編程,不符合現(xiàn)在前端MVVM的浪潮
- 基于原生的XHR開發(fā),XHR本身的架構(gòu)不清晰,已經(jīng)有了fetch的替代方案
- JQuery整個項目太大,單純使用ajax卻要引入整個JQuery非常的不合理(采取個性化打包的方案又不能享受CDN服務(wù))
Axios
Axios也是對ajax的封裝,基于Promise管理請求,解決回調(diào)地獄問題
axios({ method: 'post', url: '/user/login', data: { username: 'name', password: 'password' } }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); // 或使用 async await (async function () { let result1 = await axios.post('/user/login', { username: 'name', password: 'password' }); let result2 = await axios.get('/user/list'); console.log(result1, result2); })();
優(yōu)缺點(diǎn):
- 從瀏覽器中創(chuàng)建 XMLHttpRequest
- 從 node.js 發(fā)出 http 請求
- 支持 Promise API
- 攔截請求和響應(yīng)
- 轉(zhuǎn)換請求和響應(yīng)數(shù)據(jù)
- 取消請求
- 自動轉(zhuǎn)換JSON數(shù)據(jù)
- 客戶端支持防止CSRF/XSRF
Fetch
Fetch是ES6新增的通信方法,不是ajax,但是他本身實現(xiàn)數(shù)據(jù)通信,就是基于promise管理的
try { let response = await fetch(url, options); let data = response.json(); console.log(data); } catch(e) { console.log("Oops, error", e); }
示例:
(async function () { let result = await fetch('http://127.0.0.1:8888/user/login', { method: 'post', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: Qs.stringify({ name: 'name', password: 'password' }) }) let data = result.json(); console.log(data) ? let result2 = await fetch('http://127.0.0.1:8888/user/list').then(response => { return response.json(); }); console.log(result2); })();
優(yōu)缺點(diǎn):
- fetcht只對網(wǎng)絡(luò)請求報錯,對400,500都當(dāng)做成功的請求,需要封裝去處理
- fetch默認(rèn)不會帶cookie,需要添加配置項
- fetch不支持abort,不支持超時控制,使用setTimeout及Promise.reject的實現(xiàn)的超時控制并不能阻止請求過程繼續(xù)在后臺運(yùn)行,造成了量的浪費(fèi)
- fetch沒有辦法原生監(jiān)測請求的進(jìn)度,而XHR可以
補(bǔ)充:為什么要用axios?
axios 是一個基于Promise 用于瀏覽器和 nodejs 的 HTTP 客戶端,它本身具有以下特征:
- 從瀏覽器中創(chuàng)建 XMLHttpRequest
- 從 node.js 發(fā)出 http 請求
- 支持 Promise API
- 攔截請求和響應(yīng)
- 轉(zhuǎn)換請求和響應(yīng)數(shù)據(jù)
- 取消請求
- 自動轉(zhuǎn)換JSON數(shù)據(jù)
- 客戶端支持防止CSRF/XSRF
- axios既提供了并發(fā)的封裝,也沒有fetch的各種問題,而且體積也較小,當(dāng)之無愧現(xiàn)在最應(yīng)該選用的請求的方式。
三選一絕必是axios了。其流程圖如下:
總結(jié)
原文鏈接:https://juejin.cn/post/7083481149875421198
相關(guān)推薦
- 2022-04-16 python案例練習(xí)合集_python
- 2022-10-02 golang?NewRequest/gorequest實現(xiàn)http請求的示例代碼_Golang
- 2023-04-27 阿里低代碼框架lowcode-engine自定義設(shè)置器詳解_React
- 2023-01-11 Android開發(fā)中父組件調(diào)用子組件方法demo_Android
- 2024-07-15 SpringBoot使用Apache Poi導(dǎo)出word文檔
- 2022-05-20 詳解在SQLPlus中實現(xiàn)上下鍵翻查歷史命令的功能_MsSql
- 2022-04-25 C#利用NPOI操作Excel(單元格設(shè)置)_C#教程
- 2022-10-26 Golang?手寫一個簡單的并發(fā)任務(wù)?manager_Golang
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支