JavaScript中前后端交互Ajax示例詳解
1、Ajax概述
(1)什么是Ajax
Ajax:Asynchronous JavaScript And XML,異步JavaScript和XML技術(shù)。
描述:不是一門新的語言或技術(shù),是由JavaScript、XML、DOM、CSS等多種已有技術(shù)組合而成的一種瀏覽器端技術(shù)。
功能:用于實現(xiàn)與服務(wù)器進(jìn)行異步交互的功能。用js來實現(xiàn)頁面的局部刷新。
(2)Ajax工作流程

2、前后端交互-Ajax
(1)創(chuàng)建Ajax對象
<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ā)送請求
open(‘method’, ‘URL’ [, asyncFlag [, ‘userName’ [, ‘password’]]])
- method:用于指定請求方式,如GET、POST,不區(qū)分大小寫。
- URL:表示請求的地址。
- asyncFlag:可選參數(shù),用于指定請求方式,同步請求為false,默認(rèn)為異步請求true。
- userName和password:可選參數(shù),表示HTTP認(rèn)證的用戶名和密碼。
send(content)
- content:用于指定要發(fā)送的數(shù)據(jù),其值可為DOM對象的實例、輸入流或字符串,一般與POST請求類型配合使用。
- 注意:如果請求聲明為同步,該方法將會等待請求完成或者超時才會返回,否則此方法將立即返回。
setRequestHeader(‘haeder’, ‘value’)
- 參數(shù)都為字符串類型。
- header表示請求頭字段。
- value為該字段的值。
- 此方法必須在open()方法后調(diào)用。
<script>
// 1、創(chuàng)建ajax對象
var xhr = new XMLHttpRequest();
// 2、建立http請求
xhr.open('GET','test.php?a=1&b=2');
// 3、發(fā)送請求到web服務(wù)器并接收響應(yīng)
xhr.send();
</script>
<!-- get:適合從服務(wù)器獲取數(shù)據(jù) -->
<script>
// 1、創(chuàng)建ajax對象
var xhr = new XMLHttpRequest();
// 2、建立http請求
xhr.open('POST','test.php?a=1&b=2');
// 3、請求頭內(nèi)指定實體內(nèi)容的編碼格式
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
// 4、發(fā)送請求到web服務(wù)器并接收響應(yīng)
xhr.send('c=3&d=4');
</script>
<!-- POST:適合向服務(wù)器發(fā)生數(shù)據(jù) -->
- 在進(jìn)行Ajax開發(fā)時,經(jīng)常使用GET方式或POST方式發(fā)送請求。
- GET方式適合從服務(wù)器獲取數(shù)據(jù)。
- POST方式適合向服務(wù)器發(fā)送數(shù)據(jù)。需要設(shè)置內(nèi)容的編碼格式,告知服務(wù)器用什么樣的格式來解析數(shù)據(jù)。
注意:同步請求與異步請求
Ajax對象open()方法的第3個參數(shù)用于設(shè)置同步請求和異步請求。
兩種方式的區(qū)別在于,是否阻塞代碼的執(zhí)行。
異步方式(默認(rèn)):是非阻塞的,瀏覽器端的JavaScript程序不用等待Web服務(wù)器響應(yīng),可以繼續(xù)處理其他事情。當(dāng)服務(wù)器響應(yīng)后,再來處理Ajax對象獲取到的響應(yīng)結(jié)果。

同步方式:是阻塞的,當(dāng)Ajax對象向Web服務(wù)器發(fā)送請求后,會等待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; // 對應(yīng)狀態(tài)值0 XMLHttpRequest.OPENED; // 對應(yīng)狀態(tài)值1 XMLHttpRequest.HEADERS_RECEIVED; // 對應(yīng)狀態(tài)值2 XMLHttpRequest.LOADING; // 對應(yīng)狀態(tài)值3 XMLHttpRequest.DONE; // 對應(yīng)狀態(tài)值4 </script>
b、onreadystatechange事件屬性用于感知readyState屬性狀態(tài)的改變,每當(dāng)readyState的值發(fā)生改變時,就會調(diào)用此事件。
<script>
// 1、創(chuàng)建ajax對象
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)前請求的HTTP狀態(tài)碼,值為數(shù)值類型。
例如,當(dāng)請求成功時,狀態(tài)碼為200。
另外還有一個類似的屬性statusText,值為字符型數(shù)據(jù),包含了描述短語,如“200 OK”。
d、獲取服務(wù)器的響應(yīng)信息

responseXML屬性在請求失敗或相應(yīng)內(nèi)容無法解析時的值為null。
需要注意的是,服務(wù)器在返回XML時應(yīng)設(shè)置響應(yīng)頭Content-Type的值為text/xml或application/xml,否則會解析失敗。
<script>
// 1、創(chuàng)建對象
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ù)格式
前后端約定一種格式,確保通信雙方都能夠正確識別對方發(fā)送的信息。
(1)XML
XML:eXtensible Markup Language,可擴(kuò)展標(biāo)記語言。
與HTML都是標(biāo)簽語言,XML主要用于描述和存儲數(shù)據(jù),可以自定義標(biāo)簽。

當(dāng)服務(wù)器返回的是一個XML格式的數(shù)據(jù)時,利用Ajax對象的responseXML屬性即可對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:是一種輕量級的數(shù)據(jù)交換格式。
特點(diǎn):采用完全獨(dú)立于語言的文本格式,這使得JSON更易于程序的解析和處理。
與XML對比:使用JSON對象訪問屬性的方式獲取數(shù)據(jù)更加方便,在JavaScript中可以輕松地在JSON字符串與對象之間轉(zhuǎn)換。
<script>
var obj = {name:'Tom',age:21} //準(zhǔn)備要發(fā)生的數(shù)據(jù)
var json = JSON.stringify(obj)//將obj對象轉(zhuǎn)換為json字符串
var xhr = new XMLHttpRequest();//創(chuàng)建ajax對象
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)換為對象
console.log(obj)
// eval() 將傳入的字符串當(dāng)js代碼執(zhí)行
eval("var obj="+xhr.responseText)//用eval函數(shù)將字符型轉(zhuǎn)換為對象
console.log(obj.name)
console.log(obj.age)
}
}
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
xhr.send('json='+encodeURIComponent(json))//發(fā)送請求
</script>
4、前后端交互-跨域請求
域(Domain)是指網(wǎng)絡(luò)中獨(dú)立運(yùn)行的單位。
從網(wǎng)絡(luò)安全角度來看,域是安全的邊界,每個域都有自己的安全策略,不同域之間是隔離的,除非建立信任關(guān)系,否則無法互相訪問。
什么是跨域:未遵循同源策略,同源是指請求URL地址中的協(xié)議、域名和端口都相同
跨域請求會導(dǎo)致網(wǎng)頁失去安全性,因此瀏覽器阻止跨域請求。
(1)Access-Control-Allow-Origin響應(yīng)頭
解決辦法之一:為使受信任的網(wǎng)站之間能夠跨域訪問,HTML5提供了一個新的策略,就是Access-Control-Allow-Origin響應(yīng)頭。目標(biāo)服務(wù)器通過該響應(yīng)頭可以指定允許來自特定URL的跨域請求,其值可以設(shè)置為任意URL或特定URL等。
(2)JSONP實現(xiàn)跨域請求
JSONP:遵循瀏覽器的同源策略基礎(chǔ)上實現(xiàn)跨域請求的一種方式。
原理:與XMLHttpRequest無關(guān),是利用
JSONP之所以采用<script>標(biāo)簽,是因為該標(biāo)簽加載的資源可以直接當(dāng)做JavaScript代碼執(zhí)行,只要通過服務(wù)器端的配合,就可以傳送數(shù)據(jù)。
JSONP跨域請求。

JSONP本質(zhì)上是加載了其他網(wǎng)站的腳本,這種方式存在安全風(fēng)險,因為
其他網(wǎng)站可以利用JavaScript竊取用戶信息,或更改頁面內(nèi)容。因此,在加載腳本前,一定確保對方是受信任的網(wǎng)站。
5、其他
(1)Cookie
Cookie:或稱為Cookies,指某些網(wǎng)站為了辨別用戶身份、進(jìn)行會話(Session)跟蹤而儲存在客戶端上的數(shù)據(jù)。
相關(guān)的響應(yīng)頭:Set-Cookie字段
特點(diǎn):下次請求該網(wǎng)站時,瀏覽器會將Cookie數(shù)據(jù)放入請求頭中的Cookie字段,服務(wù)器收到這段數(shù)據(jù)即可辨認(rèn)用戶狀態(tài)。
Cookie是根據(jù)域名、路徑等參數(shù)存儲的,不同網(wǎng)站的Cookie相互隔離,從而保證數(shù)據(jù)的安全性。
(2)FormData
Ajax向服務(wù)器發(fā)送數(shù)據(jù)時,可以通過FormData收集表單中的數(shù)據(jù)。
使用方式:new FormData()實例化并傳入表單對象即可。在創(chuàng)建FormData對象后,可在調(diào)用Ajax對象的send()方法時作為參數(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對象
var xhr = new XMLHttpRequest()
// 2、建立http請求
xhr.open('post','test.php')
// 3、發(fā)送請求
xhr.send(fd)
return false;//阻止表單默認(rèn)的提交操作
}
</script>
<script>
var fd = new FormData();
fd.append('','')
</script>
(3)Promise
Promise是ES6新增的對象,用來傳遞異步操作的消息。
在代碼層面,Promise解決了異步操作的“回調(diào)地獄”問題。
“回調(diào)地獄”是指,在一個異步操作執(zhí)行完成后,執(zhí)行下一個異步操作時,出現(xiàn)回調(diào)函數(shù)嵌套回調(diào)函數(shù)的情況。如果嵌套的層級過多,會導(dǎo)致代碼可讀性變差,下面的代碼演示了這種情況。

Ajax的onreadystatechange()就是一個異步操作,若需要在一個Ajax請求完成后,再發(fā)出另一個Ajax請求,就會出現(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); // 成功時執(zhí)行的函數(shù)
} else {
reject('服務(wù)器發(fā)生錯誤。'); // 失敗時執(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('請求成功:' + data);
}, function(err) {
console.log('請求失?。? + err);
});
xhr({url: '1.txt', type: 'POST', data: fd})
.then(function(data) {
console.log('請求成功:' + data);
})
.catch(function(err) {
console.log('發(fā)生異常:' + err);
});
xhr({url: 'test.php', type: 'POST', data: fd})
.then(function(data) {
console.log('第1次請求結(jié)果:' + data);
return xhr({url: 'test.php', type: 'POST', data: fd});
})
.then(function(data) {
console.log('第2次請求結(jié)果:' + data);
})
.catch(function(err) {
console.log('發(fā)生異常:' + err);
});
</script>
(4)WebSocket
WebSocket:是HTML5新增的一個客戶端與服務(wù)器異步通信的API。
作用:用于使瀏覽器支持WebSocket網(wǎng)絡(luò)協(xié)議。
解決的問題: HTTP輪詢。
HTTP輪詢:客戶端需要不斷向服務(wù)器發(fā)送HTTP請求,詢問服務(wù)器是否有新的消息,這種方式稱為HTTP輪詢。特點(diǎn)是其通信效率非常低。
解決辦法:WebSocket實現(xiàn)了全雙工通信,在建立連接后,服務(wù)器可以將新消息主動推送給客戶端,這種方式實時性更強(qiáng),效率更高。
示例1:
<script>
// 創(chuàng)建WebSocket對象,連接服務(wù)器
var ws = new WebSocket('ws://127.0.0.1:2000');
// 當(dāng)連接成功時執(zhí)行的回調(diào)函數(shù)
ws.onopen = function() {
console.log('連接成功');
ws.send('Tom');
console.log('向服務(wù)端發(fā)送一個字符串:Tom');
};
// 當(dāng)收到服務(wù)器消息時執(zhí)行的回調(diào)函數(shù),event是事件對象
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)建一個Worker監(jiān)聽2000端口,使用WebSocket協(xié)議通訊
$ws_worker = new Worker('websocket://127.0.0.1:2000');
// 啟動4個進(jìn)程對外提供服務(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)程啟動時設(shè)置一個定時器,定時向所有客戶端連接發(fā)送數(shù)據(jù)
$worker->onWorkerStart = function($worker) {
// 每2秒一次,遍歷當(dāng)前進(jìn)程所有的客戶端連接,發(fā)送當(dāng)前服務(wù)器的時間
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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
layui在form表單頁面通過Validform加入簡單驗證的方法
今天小編就為大家分享一篇layui在form表單頁面通過Validform加入簡單驗證的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09
微信小程序項目實踐之九宮格實現(xiàn)及item跳轉(zhuǎn)功能
這篇文章主要介紹了微信小程序項目實踐之九宮格實現(xiàn)及item跳轉(zhuǎn)功能,需要的朋友可以參考下2018-07-07

