AJAX
即 Asynchronous Javascript And XML
(異步JavaScript和XML),是指一種建立交互式網頁應用的網頁開發技術。javascript
AJAX
是一種用於建立快速動態網頁的技術。它能夠令開發者只向服務器獲取數據(而不是圖片,HTML文檔等資源),互聯網資源的傳輸變得史無前例的輕量級和純粹,這激發了廣大開發者的創造力,使各式各樣功能強大的網絡站點,和互聯網應用如雨後春筍通常冒出,不斷帶給人驚喜。php
Ajax
是一種異步請求數據的web開發技術,對於改善用戶的體驗和頁面性能頗有幫助。簡單地說,在不須要從新刷新頁面的狀況下,Ajax 經過異步請求加載後臺數據,並在網頁上呈現出來。常見運用場景有表單驗證是否登入成功、百度搜索下拉框提示和快遞單號查詢等等。html
Ajax的目的是提升用戶體驗,較少網絡數據的傳輸量。同時,因爲AJAX請求獲取的是數據而不是HTML文檔,所以它也節省了網絡帶寬,讓互聯網用戶的網絡衝浪體驗變得更加順暢。前端
Ajax至關於在用戶和服務器之間加了一箇中間層,使用戶操做與服務器響應異步化。並非全部的用戶請求都提交給服務器,像一些數據驗證和數據處理等都交給Ajax引擎本身來作,只有肯定須要從服務器讀取新數據時再由Ajax引擎代爲向服務器提交請求。java
Ajax的原理簡單來講經過XmlHttpRequest對象來向服務器發送異步請求,從服務器得到數據,而後用JavaScript來操做DOM而更新頁面。這其中最關鍵的一步就是從服務器得到請求數據。要清楚這個過程和原理,咱們必須對 XMLHttpRequest有所瞭解。git
XMLHttpRequest是ajax的核心機制,它是在IE5中首先引入的,是一種支持異步請求的技術。簡單的說,也就是JavaScript能夠及時向服務器提出請求和處理響應,而不阻塞用戶。達到無刷新的效果。github
XMLHttpRequest
(記得考慮兼容性)let xhr = null;
if (window.`XMLHttpRequest`) {// 兼容 IE7+, Firefox, Chrome, Opera, Safari
xhr = new `XMLHttpRequest`();
} else {// 兼容 IE6, IE5
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
複製代碼
xhr.open(method, url, async);
send(string);//`POST`請求時才使用字符串參數,不然不用帶參數。
複製代碼
method
:請求的類型;GET
或 POST
url
:文件在服務器上的位置async
:true(異步)或 false(同步) 注意:POST
請求必定要設置請求頭的格式內容xhr.open("`POST`", "test.html", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send("fname=Henry&lname=Ford"); //`POST`請求參數放在send裏面,即請求體
複製代碼
一個Promise對象實現的 Ajax 操做的例子:web
const getJSON = function(url) {
const promise = new Promise(function(resolve, reject){
const handler = function() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
const client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
});
return promise;
};
getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('出錯了', error);
});
複製代碼
responseText
得到字符串形式的響應數據。 responseXML
得到XML 形式的響應數據。面試
xhr.open("`GET`","info.txt",false);
xhr.send();
document.`GET`ElementById("myDiv").innerHTML = xhr.responseText; //獲取數據直接顯示在頁面上
複製代碼
相對來講比較複雜,要在請求狀態改變事件中處理。ajax
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200){
document.`GET`ElementById("myDiv").innerHTML = xhr.responseText;
}
}
複製代碼
readyState
?readyState
是XMLHttpRequest
對象的一個屬性,用來標識當前XMLHttpRequest
對象處於什麼狀態。 readyState總共有5個狀態值,分別爲0~4,每一個值表明了不一樣的含義:
0
:未初始化 — 還沒有調用.open()方法;1
:啓動 — 已經調用.open()方法,但還沒有調用.send()方法;2
:發送 — 已經調用.send()方法,但還沒有接收到響應;3
:接收 — 已經接收到部分響應數據;4
:完成 — 已經接收到所有響應數據,並且已經能夠在客戶端使用了;status
?HTTP狀態碼(status)由三個十進制數字組成,第一個十進制數字定義了狀態碼的類型,後兩個數字沒有分類的做用。HTTP狀態碼共分爲5種類型:
1xx
(臨時響應):表示臨時響應並須要請求者繼續執行操做的狀態碼。2xx
(成功):表示成功處理了請求的狀態碼。3xx
(重定向):表示要完成請求,須要進一步操做。一般,這些狀態代碼用來重定向。4xx
(請求錯誤):這些狀態碼錶示請求可能出錯,妨礙了服務器的處理。5xx
(服務器錯誤):這些狀態碼錶示服務器在嘗試處理請求時發生內部錯誤。這些錯誤多是服務器自己的錯誤,而不是請求出錯。僅記錄在 RFC2616 上的 HTTP 狀態碼就達 40 種,若再加上 WebDAV(RFC491八、5842)和附加 HTTP 狀態碼 (RFC6585)等擴展,數量就達 60 餘種。接下來,咱們就介紹一下這些具備表明性的一些狀態碼。
200
表示從客戶端發來的請求在服務器端被正常處理了。204
表示請求處理成功,但沒有資源返回。301
表示永久性重定向。該狀態碼錶示請求的資源已被分配了新的URI,之後應使用資源如今所指的URI。302
表示臨時性重定向。304
表示客戶端發送附帶條件的請求時(指採用GET
方法的請求報文中包含if-matched,if-modified-since,if-none-match,if-range,if-unmodified-since任一個首部)服務器端容許請求訪問資源,但因發生請求未知足條件的狀況後,直接返回304Modified(服務器端資源未改變,可直接使用客戶端未過時的緩存)400
表示請求報文中存在語法錯誤。當錯誤發生時,需修改請求的內容後再次發送請求。401
表示未受權(Unauthorized),當前請求須要用戶驗證403
表示對請求資源的訪問被服務器拒絕了404
表示服務器上沒法找到請求的資源。除此以外,也能夠在服務器端拒絕請求且不想說明理由時使用。500
表示服務器端在執行請求時發生了錯誤。也有多是Web應用存在的bug或某些臨時的故障。503
表示服務器暫時處於超負載或正在進行停機維護,如今沒法處理請求。GET
和POST
請求數據區別GET
在瀏覽器回退時是無害的,而POST
會再次提交請求。GET
產生的URL地址能夠被Bookmark,而POST
不能夠。GET
請求會被瀏覽器主動cache,而POST
不會,除非手動設置。GET
請求只能進行url編碼,而POST
支持多種編碼方式。GET
請求參數會被完整保留在瀏覽器歷史記錄裏,而POST
中的參數不會被保留。GET
請求在URL中傳送的參數是有長度限制的,而POST
麼有。GET
只接受ASCII字符,而POST
沒有限制。GET
比POST
更不安全,由於參數直接暴露在URL上,因此不能用來傳遞敏感信息。GET
參數經過URL傳遞,POST
放在Request body中。GET
和POST
使用場景: 若符合下列任一狀況,則推薦用POST
方法:
GET
方法,則表單上收集的數據可能讓URL過長。若符合下列任一狀況,則推薦用GET
方法:
詳見本文內容=>
//建立 XMLHttpRequest 對象
var xhr = new XMLHttpRequest();
//發送信息至服務器時內容編碼類型
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//接受服務器響應數據
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && (xhr.status == 200) {
// let data = xhr.responseText;
}
};
//規定請求的類型、URL 以及是否異步處理請求。
xhr.open('GET',url,true);
//發送請求
xhr.send(null);
複製代碼
//字符串轉對象
JSON.parse(json)
eval('(' + jsonstr + ')')
// 對象轉字符串
JSON.stringify(json)
複製代碼
詳見本文內容=>
詳見本文內容=>
同源策略是瀏覽器的一個安全功能,不一樣源的客戶端腳本在沒有明確受權的狀況下,不能讀寫對方資源。因此xyz.com下的js腳本採用Ajax
讀取abc.com裏面的文件數據是會被拒絕的。
同源策略限制了從同一個源加載的文檔或腳本如何與來自另外一個源的資源進行交互。這是一個用於隔離潛在惡意文件的重要安全機制。
舉個例子:
不受同源策略限制的狀況:
JSONP 只能解決GET跨域(問的最多) **原理:**動態建立一個script標籤。利用script標籤的src屬性不受同源策略限制。由於全部的src屬性和href屬性都不受同源策略限制。能夠請求第三方服務器數據內容。 步驟: 1. 建立一個script標籤 2. script的src屬性設置接口地址 3. 接口參數,必需要帶一個自定義函數名 要否則後臺沒法返回數據。 4. 經過定義函數名去接收後臺返回數據
```js
//去建立一個script標籤
let script = document.createElement("script");
//script的src屬性設置接口地址 並帶一個callback回調函數名稱
script.src = "http://127.0.0.1:8888/index.php?callback=jsonpCallback";
//插入到頁面
document.head.appendChild(script);
//經過定義函數名去接收後臺返回數據
function jsonpCallback(data){
//注意:jsonp返回的數據是json對象能夠直接使用
//ajax 取得數據是json字符串須要轉換成json對象纔可使用。
}
```
複製代碼
CORS:跨域資源共享 原理:服務器設置Access-Control-Allow-OriginHTTP
響應頭以後,瀏覽器將會容許跨域請求 限制:瀏覽器須要支持HTML5,能夠支持POST
,PUT
等方法兼容ie9以上 須要後臺設置
Access-Control-Allow-Origin: * //容許全部域名訪問,或者
Access-Control-Allow-Origin: http://a.com //只容許全部域名訪問
複製代碼
設置 document.domain 原理:相同主域名不一樣子域名下的頁面,能夠設置document.domain
讓它們同域 限制:同域document提供的是頁面間的互操做,須要載入iframe頁面
// URL http://a.com/foo
var ifr = document.createElement('iframe');
ifr.src = 'http://b.a.com/bar';
ifr.onload = function(){
var ifrdoc = ifr.contentDocument || ifr.contentWindow.document;
ifrdoc.getElementsById("foo").innerHTML);
};
ifr.style.display = 'none';
document.body.appendChild(ifr);
複製代碼
ES5 postMessage ES5新增的 postMessage()
方法容許來自不一樣源的腳本採用異步方式進行有限的通訊,能夠實現跨文本檔、多窗口、跨域消息傳遞. 語法:
postMessage(data,origin)
複製代碼
用Apache作轉發(逆向代理),讓跨域變成同域
其實經過 XMLHttpRequest
或者封裝後的框架進行網絡請求,這種方式已經有點老舊了,配置和調用方式很是混亂,近幾年剛剛出來的Fetch提供了一個更好的替代方法,它不只提供了一種簡單,合乎邏輯的方式來跨網絡異步獲取資源,並且能夠很容易地被其餘技術使用。
推薦閱讀:
參考:
Ajax原理一篇就夠了 · Issue #45 · ljianshu/Blog · GitHub
HTTP菜鳥教程 Ajax MDN文檔 ajax常見的面試問題 - 斧子兔 - 博客園
我是Cloudy,現居上海,年輕的前端攻城獅一枚,愛專研,愛技術,愛分享。 我的筆記,整理不易,感謝
關注
、閱讀
、點贊
和收藏
。 文章有任何問題歡迎你們指出,也歡迎你們一塊兒交流各類前端問題!