從零開始學 Web 之 Ajax(五)同步異步請求,數據格式
大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新......
- github:https://github.com/Daotin/Web
- 微信公眾號:Web前端之巔
- 博客園:http://www.cnblogs.com/lvonve/
- CSDN:https://blog.csdn.net/lvonve/
在這裏我會從 Web 前端零基礎開始,一步步學習 Web 相關的知識點,期間也會分享一些好玩的項目。現在就讓我們一起進入 Web 前端學習的冒險之旅吧!
一、同步請求與異步請求
同步請求:在用戶進行請求發送之後,瀏覽器會一直等待服務器的數據返回,如果網絡延遲比較高,瀏覽器就一直卡在當前界面,直到服務器返回數據才可進行其他操作。
異步請求:在用戶進行請求發送之後,瀏覽器可以自由操作頁面中其他的元素,當服務器放回數據的時候,才觸發相應事件,對返回的數據進行操作。
如果將 Ajax 請求改為同步請求的話:
1、界面會卡頓,卡頓事件取決於網絡速度;
2、xhr.onreadystatechange 的回調函數不會執行,因為在 xhr.send() 之後,xhr.readyState 就為 4 了,所以數據的處理,直接跟在xhr.send() 之後就可以了。
1、異步的底層原理
js 中的異步實現原理是單線程+事件隊列。js 的代碼執行是單線程的,單線程的意思是代碼從上到下按照順序執行,而事件隊列存儲了一些回調函數,當 js 從上往下執行的時候,遇到回調函數就將其放到事件隊列,在所有 js 代碼執行完成之後處於空閑狀態時,才會去事件隊列看有沒有回調函數達到觸發條件,有的話就執行,沒有的話就繼續閑著。
Ajax 的四步操作中,同步和異步的區別:
如果是異步請求,在 send 的時候,會調用瀏覽器進行網絡數據的請求,send 就執行完了,接著將第四步的回調函數存儲在事件隊列裏面,瀏覽器數據請求完了,readyState 狀態發生變化,觸發第四步回調函數的執行。
而在同步請求中, send 時是自己進行網絡數據的請求,這個時候非得請求到數據,才會接著將第四步的回調函數存儲在事件隊列裏面,所以如果網絡延時頁面就會卡死,在 send 過後接受到數據的時候 readyState 已經為4了,不會再變化,所以第四步的回調函數不會執行。
二、數據格式
什麽是數據格式?
數據格式就是通過一定的規範組織起來,叫做數據格式。
1、XML 數據格式
XML 數據格式是將數據以標簽的方式進行組裝,必須以 <? xml version="1.0" encoding="utf-8" ?>
開頭,標簽必須成對出現,也就是有開始標簽就一定要有結束標簽。
<? xml version="1.0" encoding="utf-8" ?>
<students>
<student>
<name>張三</name>
<age>18</age>
<sex>男</sex>
</student>
</students>
缺點:體積太大,元數據(描述數據的數據)太多,解析不方便,目前使用很少。
2、json 數據格式
json 數據格式通過 key-value 的方式組裝。
{
"student" : [
{
"name": "張三",
"age": "18",
"sex": "男"
},
{
"name": "李四",
"age": "23",
"sex": "女"
}
]
}
優點:體積小,傳輸快,解析方便。
3、案例:獲取圖書信息
接口文檔:
地址 | /server/getBooks/php |
---|---|
作用描述 | 獲取圖書信息 |
請求類型 | get 請求 |
參數 | 無 |
返回數據格式 | xml 格式 |
返回數據說明 | 如下 |
<?xml version="1.0" encoding="utf-8" ?>
<booklist>
<book>
<name>三國演義</name>
<author>羅貫中</author>
<desc>一個殺伐紛爭的年代</desc>
</book>
<book>
<name>水滸傳</name>
<author>施耐庵</author>
<desc>108條好漢的故事</desc>
</book>
<book>
<name>西遊記</name>
<author>吳承恩</author>
<desc>佛教與道教鬥爭</desc>
</book>
<book>
<name>紅樓夢</name>
<author>曹雪芹</author>
<desc>一個封建王朝的縮影</desc>
</book>
</booklist>
源代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>書籍列表</title>
<style>
div{
width: 800px;
margin: 20px auto;
}
table{
width: 800px;
margin: 20px auto;
border-collapse: collapse;
}
th{
background-color: #0094ff;
color:white;
font-size: 16px;
padding: 5px;
text-align: center;
border: 1px solid black;
}
td{
padding: 5px;
text-align: center;
border: 1px solid black;
}
</style>
<script>
window.onload = function () {
var xhr = new XMLHttpRequest();
xhr.open("get", "./server/getBooks.php", true);
xhr.send(null);
xhr.onreadystatechange = function () {
if(this.readyState == 4) {
if(this.status = 200) {
var booklists = this.responseXML.getElementsByTagName("booklist")[0].getElementsByTagName("book");
for(var i=0; i<booklists.length; i++) {
var name = booklists[i].getElementsByTagName("name")[0].textContent;
var author = booklists[i].getElementsByTagName("author")[0].textContent;
var desc = booklists[i].getElementsByTagName("desc")[0].textContent;
var trObj = document.createElement("tr");
trObj.innerHTML = "<td>"+name+"</td><td>"+author+"</td><td>"+desc+"</td>";
document.getElementsByTagName("table")[0].appendChild(trObj);
}
}
}
};
};
</script>
</head>
<body>
<div>
<table>
<tr>
<th>書名</th>
<th>作者</th>
<th>描述</th>
</tr>
<!-- <tr>
<td>三國演義</td>
<td>羅貫中</td>
<td>一個殺伐紛爭的年代</td>
</tr> -->
</table>
</div>
</body>
</html>
XML 數據的格式主要是通過:getElementsByTagName 來獲取的。
4、案例:獲取學生信息
接口文檔:
地址 | /server/getStudents/php |
---|---|
作用描述 | 獲取學生信息 |
請求類型 | get 請求 |
參數 | 無 |
返回數據格式 | json 格式 |
返回數據說明 | 如下 |
[
{
"name":"張三",
"age":"18",
"sex":"男"
}
]
源代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>學生列表</title>
<style>
div{
width: 800px;
margin: 20px auto;
}
table{
width: 800px;
margin: 20px auto;
border-collapse: collapse;
}
th{
background-color: #0094ff;
color:white;
font-size: 16px;
padding: 5px;
text-align: center;
border: 1px solid black;
}
td{
padding: 5px;
text-align: center;
border: 1px solid black;
}
</style>
<script>
window.onload = function () {
var xhr = new XMLHttpRequest();
xhr.open("get", "./server/getStudents.php", true);
xhr.send(null);
xhr.onreadystatechange = function () {
if(this.readyState == 4) {
if(this.status = 200) {
var jsonObj = JSON.parse(this.responseText);
for(var i=0; i<jsonObj.length; i++) {
var name = jsonObj[i].name;
var age = jsonObj[i].age;
var sex = jsonObj[i].sex;
var trObj = document.createElement("tr");
trObj.innerHTML = "<td>"+name+"</td><td>"+age+"</td><td>"+sex+"</td>";
document.getElementsByTagName("table")[0].appendChild(trObj);
}
}
}
};
};
</script>
</head>
<body>
<div>
<table>
<tr>
<th>姓名</th>
<th>年齡</th>
<th>性別</th>
</tr>
<!-- <tr>
<td>張三</td>
<td>20</td>
<td>男</td>
</tr> -->
</table>
</div>
</body>
</html>
只需要將獲取的 responseText 轉化為 json 格式的對象,使用
JSON.parse(this.responseText);
從零開始學 Web 之 Ajax(五)同步異步請求,數據格式