JavaScript中前后端交互Ajax示例詳解
1、Ajax概述
(1)什么是Ajax
Ajax:Asynchronous JavaScript And XML,異步JavaScript和XML技術(shù)。
描述:不是一門新的語(yǔ)言或技術(shù),是由JavaScript、XML、DOM、CSS等多種已有技術(shù)組合而成的一種瀏覽器端技術(shù)。
功能:用于實(shí)現(xiàn)與服務(wù)器進(jìn)行異步交互的功能。用js來實(shí)現(xiàn)頁(yè)面的局部刷新。
(2)Ajax工作流程
2、前后端交互-Ajax
(1)創(chuàng)建Ajax對(duì)象
<script> //W3C標(biāo)準(zhǔn) var xhr = new XMLHttpRequest(); </script> <script> //早期IE瀏覽器 var xhr = new ActiveXObject('Microsoft.XMLHTTP'); var xhr = new ActiveXObject('Msxml2.XMLHTTP'); var xhr = new ActiveXObject('Msxml2.XMLHTTP.3.0'); var xhr = new ActiveXObject('Msxml2.XMLHTTP.5.0'); var xhr = new ActiveXObject('Msxml2.XMLHTTP.6.0'); </script>
(2)Ajax向服務(wù)器發(fā)送請(qǐng)求
open(‘method’, ‘URL’ [, asyncFlag [, ‘userName’ [, ‘password’]]])
- method:用于指定請(qǐng)求方式,如GET、POST,不區(qū)分大小寫。
- URL:表示請(qǐng)求的地址。
- asyncFlag:可選參數(shù),用于指定請(qǐng)求方式,同步請(qǐng)求為false,默認(rèn)為異步請(qǐng)求true。
- userName和password:可選參數(shù),表示HTTP認(rèn)證的用戶名和密碼。
send(content)
- content:用于指定要發(fā)送的數(shù)據(jù),其值可為DOM對(duì)象的實(shí)例、輸入流或字符串,一般與POST請(qǐng)求類型配合使用。
- 注意:如果請(qǐng)求聲明為同步,該方法將會(huì)等待請(qǐng)求完成或者超時(shí)才會(huì)返回,否則此方法將立即返回。
setRequestHeader(‘haeder’, ‘value’)
- 參數(shù)都為字符串類型。
- header表示請(qǐng)求頭字段。
- value為該字段的值。
- 此方法必須在open()方法后調(diào)用。
<script> // 1、創(chuàng)建ajax對(duì)象 var xhr = new XMLHttpRequest(); // 2、建立http請(qǐng)求 xhr.open('GET','test.php?a=1&b=2'); // 3、發(fā)送請(qǐng)求到web服務(wù)器并接收響應(yīng) xhr.send(); </script> <!-- get:適合從服務(wù)器獲取數(shù)據(jù) -->
<script> // 1、創(chuàng)建ajax對(duì)象 var xhr = new XMLHttpRequest(); // 2、建立http請(qǐng)求 xhr.open('POST','test.php?a=1&b=2'); // 3、請(qǐng)求頭內(nèi)指定實(shí)體內(nèi)容的編碼格式 xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded') // 4、發(fā)送請(qǐng)求到web服務(wù)器并接收響應(yīng) xhr.send('c=3&d=4'); </script> <!-- POST:適合向服務(wù)器發(fā)生數(shù)據(jù) -->
- 在進(jìn)行Ajax開發(fā)時(shí),經(jīng)常使用GET方式或POST方式發(fā)送請(qǐng)求。
- GET方式適合從服務(wù)器獲取數(shù)據(jù)。
- POST方式適合向服務(wù)器發(fā)送數(shù)據(jù)。需要設(shè)置內(nèi)容的編碼格式,告知服務(wù)器用什么樣的格式來解析數(shù)據(jù)。
注意:同步請(qǐng)求與異步請(qǐng)求
Ajax對(duì)象open()方法的第3個(gè)參數(shù)用于設(shè)置同步請(qǐng)求和異步請(qǐng)求。
兩種方式的區(qū)別在于,是否阻塞代碼的執(zhí)行。
異步方式(默認(rèn)):是非阻塞的,瀏覽器端的JavaScript程序不用等待Web服務(wù)器響應(yīng),可以繼續(xù)處理其他事情。當(dāng)服務(wù)器響應(yīng)后,再來處理Ajax對(duì)象獲取到的響應(yīng)結(jié)果。
同步方式:是阻塞的,當(dāng)Ajax對(duì)象向Web服務(wù)器發(fā)送請(qǐng)求后,會(huì)等待Web服務(wù)器響應(yīng)的數(shù)據(jù)接收完成,再繼續(xù)執(zhí)行后面的代碼。
(3)處理服務(wù)器返回的信息
a、readyState屬性用于獲取Ajax的當(dāng)前狀態(tài),狀態(tài)值有5種形式。
Ajax狀態(tài)的還可以通過“XMLHttpRequest.屬性名”的方式獲取。
<script> XMLHttpRequest.UNSENT; // 對(duì)應(yīng)狀態(tài)值0 XMLHttpRequest.OPENED; // 對(duì)應(yīng)狀態(tài)值1 XMLHttpRequest.HEADERS_RECEIVED; // 對(duì)應(yīng)狀態(tài)值2 XMLHttpRequest.LOADING; // 對(duì)應(yīng)狀態(tài)值3 XMLHttpRequest.DONE; // 對(duì)應(yīng)狀態(tài)值4 </script>
b、onreadystatechange事件屬性用于感知readyState屬性狀態(tài)的改變,每當(dāng)readyState的值發(fā)生改變時(shí),就會(huì)調(diào)用此事件。
<script> // 1、創(chuàng)建ajax對(duì)象 var xhr = new XMLHttpRequest() console.log(xhr.readyState)//0 xhr.onreadystatechange = function(){ console.log(xhr.readyState)//1,2,3,4 } xhr.open('get','test.php') xhr.send() </script>
c、status屬性用于返回當(dāng)前請(qǐng)求的HTTP狀態(tài)碼,值為數(shù)值類型。
例如,當(dāng)請(qǐng)求成功時(shí),狀態(tài)碼為200。
另外還有一個(gè)類似的屬性statusText,值為字符型數(shù)據(jù),包含了描述短語(yǔ),如“200 OK”。
d、獲取服務(wù)器的響應(yīng)信息
responseXML屬性在請(qǐng)求失敗或相應(yīng)內(nèi)容無法解析時(shí)的值為null。
需要注意的是,服務(wù)器在返回XML時(shí)應(yīng)設(shè)置響應(yīng)頭Content-Type的值為text/xml或application/xml,否則會(huì)解析失敗。
<script> // 1、創(chuàng)建對(duì)象 var xhr = new XMLHttpRequest(); // 2、事件屬性 xhr.onreadystatechange = function(){ // xhr.readyState 獲取狀態(tài)值 1,2,3,4 if(xhr.readyState === XMLHttpRequest.DONE){ // status 響應(yīng)狀態(tài)碼 if(xhr.status<200 || xhr.status>=300 && xhr.status !== 304){ alert('服務(wù)器異常'); return; } // xhr.responseText //Hello console.log(xhr.responseText) document.write('<h2>'+xhr.responseText+'</h2>') } } xhr.open('get','hello.php') xhr.send() </script>
注意:URL參數(shù)編碼轉(zhuǎn)換
<script> var str = encodeURIComponent('A&B C'); var url = 'http://xxx/test.php?name=' + str; console.log(url); // 輸出結(jié)果:http://xxx/test.php?name=A%26B%20C </script> <script> var str = 'A%26B%20C'; console.log(decodeURIComponent(str)); // 輸出結(jié)果:A&B C </script>
3、前后端交互-數(shù)據(jù)格式
前后端約定一種格式,確保通信雙方都能夠正確識(shí)別對(duì)方發(fā)送的信息。
(1)XML
XML:eXtensible Markup Language,可擴(kuò)展標(biāo)記語(yǔ)言。
與HTML都是標(biāo)簽語(yǔ)言,XML主要用于描述和存儲(chǔ)數(shù)據(jù),可以自定義標(biāo)簽。
當(dāng)服務(wù)器返回的是一個(gè)XML格式的數(shù)據(jù)時(shí),利用Ajax對(duì)象的responseXML屬性即可對(duì)XML數(shù)據(jù)進(jìn)行處理。
<script> var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if(xhr.readyState === XMLHttpRequest.DONE){ var data = xhr.responseXML; var booklist = data.getElementsByTagName('booklist')[0];//<booklist>...</booklist> console.log(booklist.childNodes)//[text\book\text] console.log(booklist.children)//[book] var book = booklist.children[0]//<book>...</book> console.log(book.children)//[name,author] console.log(book.children[0].innerHTML)//西游記 console.log(book.children[0].firstChild)// '西游記' console.log(book.children[0].firstChild.wholeText)//西游記 } } xhr.open('get','xml.php') xhr.send() </script>
(2)JSON
JSON:是一種輕量級(jí)的數(shù)據(jù)交換格式。
特點(diǎn):采用完全獨(dú)立于語(yǔ)言的文本格式,這使得JSON更易于程序的解析和處理。
與XML對(duì)比:使用JSON對(duì)象訪問屬性的方式獲取數(shù)據(jù)更加方便,在JavaScript中可以輕松地在JSON字符串與對(duì)象之間轉(zhuǎn)換。
<script> var obj = {name:'Tom',age:21} //準(zhǔn)備要發(fā)生的數(shù)據(jù) var json = JSON.stringify(obj)//將obj對(duì)象轉(zhuǎn)換為json字符串 var xhr = new XMLHttpRequest();//創(chuàng)建ajax對(duì)象 xhr.open('post','json.php');//建立連接 xhr.onreadystatechange = function(){ if(xhr.readyState === XMLHttpRequest.DONE){ console.log(typeof xhr.responseText)//查看服務(wù)器返回的數(shù)據(jù)類型:string var obj = JSON.parse(xhr.responseText)//將json字符串轉(zhuǎn)換為對(duì)象 console.log(obj) // eval() 將傳入的字符串當(dāng)js代碼執(zhí)行 eval("var obj="+xhr.responseText)//用eval函數(shù)將字符型轉(zhuǎn)換為對(duì)象 console.log(obj.name) console.log(obj.age) } } xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded') xhr.send('json='+encodeURIComponent(json))//發(fā)送請(qǐng)求 </script>
4、前后端交互-跨域請(qǐng)求
域(Domain)是指網(wǎng)絡(luò)中獨(dú)立運(yùn)行的單位。
從網(wǎng)絡(luò)安全角度來看,域是安全的邊界,每個(gè)域都有自己的安全策略,不同域之間是隔離的,除非建立信任關(guān)系,否則無法互相訪問。
什么是跨域:未遵循同源策略,同源是指請(qǐng)求URL地址中的協(xié)議、域名和端口都相同
跨域請(qǐng)求會(huì)導(dǎo)致網(wǎng)頁(yè)失去安全性,因此瀏覽器阻止跨域請(qǐng)求。
(1)Access-Control-Allow-Origin響應(yīng)頭
解決辦法之一:為使受信任的網(wǎng)站之間能夠跨域訪問,HTML5提供了一個(gè)新的策略,就是Access-Control-Allow-Origin響應(yīng)頭。目標(biāo)服務(wù)器通過該響應(yīng)頭可以指定允許來自特定URL的跨域請(qǐng)求,其值可以設(shè)置為任意URL或特定URL等。
(2)JSONP實(shí)現(xiàn)跨域請(qǐng)求
JSONP:遵循瀏覽器的同源策略基礎(chǔ)上實(shí)現(xiàn)跨域請(qǐng)求的一種方式。
原理:與XMLHttpRequest無關(guān),是利用
JSONP之所以采用<script>標(biāo)簽,是因?yàn)樵摌?biāo)簽加載的資源可以直接當(dāng)做JavaScript代碼執(zhí)行,只要通過服務(wù)器端的配合,就可以傳送數(shù)據(jù)。
JSONP跨域請(qǐng)求。
JSONP本質(zhì)上是加載了其他網(wǎng)站的腳本,這種方式存在安全風(fēng)險(xiǎn),因?yàn)?/p>
其他網(wǎng)站可以利用JavaScript竊取用戶信息,或更改頁(yè)面內(nèi)容。因此,在加載腳本前,一定確保對(duì)方是受信任的網(wǎng)站。
5、其他
(1)Cookie
Cookie:或稱為Cookies,指某些網(wǎng)站為了辨別用戶身份、進(jìn)行會(huì)話(Session)跟蹤而儲(chǔ)存在客戶端上的數(shù)據(jù)。
相關(guān)的響應(yīng)頭:Set-Cookie字段
特點(diǎn):下次請(qǐng)求該網(wǎng)站時(shí),瀏覽器會(huì)將Cookie數(shù)據(jù)放入請(qǐng)求頭中的Cookie字段,服務(wù)器收到這段數(shù)據(jù)即可辨認(rèn)用戶狀態(tài)。
Cookie是根據(jù)域名、路徑等參數(shù)存儲(chǔ)的,不同網(wǎng)站的Cookie相互隔離,從而保證數(shù)據(jù)的安全性。
(2)FormData
Ajax向服務(wù)器發(fā)送數(shù)據(jù)時(shí),可以通過FormData收集表單中的數(shù)據(jù)。
使用方式:new FormData()實(shí)例化并傳入表單對(duì)象即可。在創(chuàng)建FormData對(duì)象后,可在調(diào)用Ajax對(duì)象的send()方法時(shí)作為參數(shù)傳入,從而將表單數(shù)據(jù)發(fā)送給服務(wù)器。
<form id="form"> 姓名:<input type="text" name="name"><br> 密碼:<input type="password" name="pass"><br> 郵箱:<input type="text" name="email"><br> <input type="submit" value="提交"> </form> <script> document.getElementById('form').onsubmit = function(){ var fd = new FormData(this); // 1、創(chuàng)建ajax對(duì)象 var xhr = new XMLHttpRequest() // 2、建立http請(qǐng)求 xhr.open('post','test.php') // 3、發(fā)送請(qǐng)求 xhr.send(fd) return false;//阻止表單默認(rèn)的提交操作 } </script> <script> var fd = new FormData(); fd.append('','') </script>
(3)Promise
Promise是ES6新增的對(duì)象,用來傳遞異步操作的消息。
在代碼層面,Promise解決了異步操作的“回調(diào)地獄”問題。
“回調(diào)地獄”是指,在一個(gè)異步操作執(zhí)行完成后,執(zhí)行下一個(gè)異步操作時(shí),出現(xiàn)回調(diào)函數(shù)嵌套回調(diào)函數(shù)的情況。如果嵌套的層級(jí)過多,會(huì)導(dǎo)致代碼可讀性變差,下面的代碼演示了這種情況。
Ajax的onreadystatechange()就是一個(gè)異步操作,若需要在一個(gè)Ajax請(qǐng)求完成后,再發(fā)出另一個(gè)Ajax請(qǐng)求,就會(huì)出現(xiàn)回調(diào)函數(shù)嵌套情況。
<script> function xhr(options) { return new Promise(function(resolve, reject) { var xhr = new XMLHttpRequest(); xhr.open(options.type || 'GET', options.url); xhr.onreadystatechange = function() { if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) { resolve(xhr.responseText); // 成功時(shí)執(zhí)行的函數(shù) } else { reject('服務(wù)器發(fā)生錯(cuò)誤。'); // 失敗時(shí)執(zhí)行的函數(shù) } } }; xhr.send(options.data); }); } var fd = new FormData(); fd.append('num', 100); xhr({url: 'test.php', type: 'POST', data: fd}) .then(function(data) { console.log('請(qǐng)求成功:' + data); }, function(err) { console.log('請(qǐng)求失敗:' + err); }); xhr({url: '1.txt', type: 'POST', data: fd}) .then(function(data) { console.log('請(qǐng)求成功:' + data); }) .catch(function(err) { console.log('發(fā)生異常:' + err); }); xhr({url: 'test.php', type: 'POST', data: fd}) .then(function(data) { console.log('第1次請(qǐng)求結(jié)果:' + data); return xhr({url: 'test.php', type: 'POST', data: fd}); }) .then(function(data) { console.log('第2次請(qǐng)求結(jié)果:' + data); }) .catch(function(err) { console.log('發(fā)生異常:' + err); }); </script>
(4)WebSocket
WebSocket:是HTML5新增的一個(gè)客戶端與服務(wù)器異步通信的API。
作用:用于使瀏覽器支持WebSocket網(wǎng)絡(luò)協(xié)議。
解決的問題: HTTP輪詢。
HTTP輪詢:客戶端需要不斷向服務(wù)器發(fā)送HTTP請(qǐng)求,詢問服務(wù)器是否有新的消息,這種方式稱為HTTP輪詢。特點(diǎn)是其通信效率非常低。
解決辦法:WebSocket實(shí)現(xiàn)了全雙工通信,在建立連接后,服務(wù)器可以將新消息主動(dòng)推送給客戶端,這種方式實(shí)時(shí)性更強(qiáng),效率更高。
示例1:
<script> // 創(chuàng)建WebSocket對(duì)象,連接服務(wù)器 var ws = new WebSocket('ws://127.0.0.1:2000'); // 當(dāng)連接成功時(shí)執(zhí)行的回調(diào)函數(shù) ws.onopen = function() { console.log('連接成功'); ws.send('Tom'); console.log('向服務(wù)端發(fā)送一個(gè)字符串:Tom'); }; // 當(dāng)收到服務(wù)器消息時(shí)執(zhí)行的回調(diào)函數(shù),event是事件對(duì)象 ws.onmessage = function(event) { console.log('收到服務(wù)器消息:' + event.data); }; </script>
<?php // 載入Workerman use Workerman\Worker; require_once __DIR__ . '/workerman-for-win-master/Autoloader.php'; // 創(chuàng)建一個(gè)Worker監(jiān)聽2000端口,使用WebSocket協(xié)議通訊 $ws_worker = new Worker('websocket://127.0.0.1:2000'); // 啟動(dòng)4個(gè)進(jìn)程對(duì)外提供服務(wù) $ws_worker->count = 4; // 當(dāng)收到客戶端發(fā)來的數(shù)據(jù)$data后返回給客戶端 $ws_worker->onMessage = function($connection, $data) { // 向客戶端發(fā)送Hello $data $connection->send('Hello ' . $data); }; // 運(yùn)行Worker Worker::runAll();
示例2:
<script> var ws = new WebSocket('ws://127.0.0.1:2000'); ws.onopen = function() { console.log('連接成功'); }; ws.onmessage = function(e) { console.log('收到服務(wù)器消息:' + e.data); }; </script>
<?php use Workerman\Worker; use Workerman\Lib\Timer; require_once __DIR__ . '/workerman-for-win-master/Autoloader.php'; $worker = new Worker('websocket://127.0.0.1:2000'); // 進(jìn)程啟動(dòng)時(shí)設(shè)置一個(gè)定時(shí)器,定時(shí)向所有客戶端連接發(fā)送數(shù)據(jù) $worker->onWorkerStart = function($worker) { // 每2秒一次,遍歷當(dāng)前進(jìn)程所有的客戶端連接,發(fā)送當(dāng)前服務(wù)器的時(shí)間 Timer::add(2, function() use($worker) { foreach($worker->connections as $connection) { $connection->send(time()); } }); }; Worker::runAll();
總結(jié)
到此這篇關(guān)于JavaScript中前后端交互Ajax的文章就介紹到這了,更多相關(guān)JS前后端交互Ajax內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
前端圖片懶加載的原理與3種實(shí)現(xiàn)方式舉例
圖片懶加載又稱圖片延時(shí)加載、惰性加載,即在用戶需要使用圖片的時(shí)候加載,這樣可以減少請(qǐng)求,節(jié)省帶寬,提高頁(yè)面加載速度,相對(duì)的,也能減少服務(wù)器壓力,下面這篇文章主要給大家介紹了關(guān)于前端圖片懶加載的原理與3種實(shí)現(xiàn)方式的相關(guān)資料,需要的朋友可以參考下2023-03-03Openlayers實(shí)現(xiàn)地圖的基本操作
這篇文章主要為大家詳細(xì)介紹了Openlayers實(shí)現(xiàn)地圖的基本操作,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09詳解JavaScript基于面向?qū)ο笾^承實(shí)例
這篇文章主要介紹了JavaScript基于面向?qū)ο笾^承實(shí)例,需要的朋友可以參考下2015-12-12layui在form表單頁(yè)面通過Validform加入簡(jiǎn)單驗(yàn)證的方法
今天小編就為大家分享一篇layui在form表單頁(yè)面通過Validform加入簡(jiǎn)單驗(yàn)證的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-09-09微信小程序項(xiàng)目實(shí)踐之九宮格實(shí)現(xiàn)及item跳轉(zhuǎn)功能
這篇文章主要介紹了微信小程序項(xiàng)目實(shí)踐之九宮格實(shí)現(xiàn)及item跳轉(zhuǎn)功能,需要的朋友可以參考下2018-07-07JS模仿手機(jī)端九宮格登錄功能實(shí)現(xiàn)代碼
這篇文章主要介紹了JS模仿手機(jī)端九宮格登錄功能實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2016-04-04