含義: async javascript and xml 異步的js和xml
javascript
//1、建立Ajax實例
let xhr = new XMLHttpRequest();//IE下爲ActiveObject對象
//2、打開請求: 發送請求以前的一些配置項
//1.HTTP METHOD:GET/POST/PUT/DELETE/HEAD/OPTIONS/TRACE/CONNECT/
//2.url:接口地址
//3.async:設置Ajax的同步異步,默認是異步
//4.user-name/user-pass用戶名和密碼,通常不用
xhr.open(method, url, async, [user-name], [user-pass])
//3、事件監聽:通常監聽的都是readystatechange事件(Ajax狀態改變事件),基於這個事件能夠獲取服務器返回的響應頭響應主體
xhr.onreadystatechange = () => {
if(xhr.readyState === 4 && xhr.status === 200){
console.log(xhr.responseText);
}
};
//4、發送Ajax請求:從這步開始,當前Ajax任務開始,若是Ajax是同步的,後續代碼不會執行,要等到Ajax狀態成功後再執行
xhr.send([請求主體內容])
複製代碼
GET經過url字符串傳參,POST經過請求主體java
[GET]
xhr.open('GET', '/tmp/list?xxx=xxx&xxx=xxx')
[POST]
xhr.send('xxx=xxx')
(通常是url-encode格式)
複製代碼
由於 GET是基於」問號傳參「把信息傳遞給服務器的,容易被hack進行url劫持,post是基於請求主體傳遞的。ios
不可控:是瀏覽器的自主記憶,沒法經過JS控制。 解決方案ajax
xhr.open('GET', `/temp/list?lx=1000&_=${Math.random()}`);
複製代碼
0 => UNSENT 剛開始建立xhr, 尚未發送編程
1 => OPENED 已經執行了open這個操做json
2 => HEADERS_RESERVED 已經發送Ajax,響應頭已經被客戶端接受axios
3 => LOADING 響應主體內容正在返回設計模式
4 => DONE 響應主體已經被客戶端接收跨域
根據狀態碼可以清楚的反映出當前交互的結果和緣由瀏覽器
1XX :指示信息-表示請求已接受、繼續處理
2XX :成功 - 表示請求已被成功接收
3XX :成功,可是已經重定向
4XX : 客戶端錯誤
5XX : 服務端錯誤
具體舉例:
200 OK: 客戶端請求成功
206 Partial Content: 客戶發送了一個帶有Range頭的GET請求,服務器完成了它
301 Moved Permamently: 已經永久轉至新的url
302 Found: 臨時轉至新的url,當一臺服務器達到最大併發數,會轉移服務器處理
304 Not Modified: 服務器告訴客戶,原來的緩存能夠繼續使用,如CSS/JS/HTML/IMG,Ctrl+F5 304緩存失效
400 Bad Request: 客戶端有語法錯誤,服務器不能理解
401 Unauthorized: 請求未經受權
403 Forbidden: 對被請求頁面的訪問被禁止
404 Not Found: 請求資源不存在
413 Request Entity Too Large 和服務器交互的內容資源超過最大大小
500 Interval Server Error 服務器錯誤,原來的緩存還能使用
503 Service Unavailable
xhr.response 響應主體內容
xhr.responseText 響應的內容是字符串(JSON或XML文檔)
xhr.responseXML 響應的內容是xml
xhr.status 返回的HTTP狀態碼
xhr.statusText 狀態碼的描述
xhr.timeout 設置請求超時的時間
xhr.timeout = 1000
xhr.ontimeout = () => {
console.log(‘請求超時’)
}
複製代碼
xhr.withCredentials 是否容許跨域(false)
xhr.abort() 強制中斷Ajax請求
xhr.abort();
xhr.onabort = () => {}
複製代碼
xhr.getAllResponseHeaders() 獲取全部響應頭信息
xhr.getResponseHeader([key])例如:xhr.getResponseHeader('date')就是獲取響應頭中的服務器時間
xhr.open() 打開url請求
xhr.overrideMimeType() 重寫MIME類型
xhr.send()發送Ajax請求,參數爲請求主體對象
xhr.setRequestHeader() 設置自定義請求頭信息(不能出現中文),必須在open以後設置
//小例子
xhr.onreadystatechange = () => {
if(!/^(2|3)\d{2}$/.test(xhr.status))return;//證實服務器已經返回內容了
if(xhr.readyState === 2){
let time = xhr.getResponseHeader('date');
}
if(xhr.readyState === 4 && xhr.status === 200){
JSON.parse(xhr.responseText);
}
}
複製代碼
異步:
let xhr = new XMLHttpRequest();
xhr.open('GET', 'xxx', true);
xhr.onreadystatechange = () => {
if(xhr.readyState === 2) {
console.log(1);
}
if(xhr.readyState === 4) {
console.log(2)
}
}
xhr.send();
console.log(3)
//3 1 2
複製代碼
同步:
let xhr = new XMLHttpRequest();
xhr.open('GET', 'xxx', false);
xhr.onreadystatechange = () => {
if(xhr.readyState === 2) {
console.log(1);
}
if(xhr.readyState === 4) {
console.log(2)
}
}
xhr.send(); //任務開始,只要當前Ajax請求這件事沒完成(readyState沒到4),什麼都不能作
console.log(3)
//2 3 爲何呢?
//因爲是同步編程,主任務隊列在狀態沒有變成4以前一直被Ajax請求佔用,其餘事件作不了。
//因此,只有readyState變成4才能執行方法。
let xhr = new XMLHttpRequest();
xhr.open('GET', 'xxx', false);
xhr.send(); //任務開始,只要當前Ajax請求這件事沒完成(readyState沒到4),什麼都不能作
//如今狀態已經爲4
xhr.onreadystatechange = () => {
if(xhr.readyState === 2) {
console.log(1);
}
if(xhr.readyState === 4) {
console.log(2)
}
}
console.log(3)
//3
//所以採用異步Ajax
複製代碼
/** * DATA: * 若是是GET請求是基於問號傳參過去的 * 若是是POST請求是基於請求主體傳遞過去的 * data的值能夠是對象也能夠是字符串(通常經常使用對象): * 若是是對象,jq會把對象轉換爲 xxx=xxx 的模式(x-www-form-urlencoded) * DATA-TYPE:預設置獲取結果的數據格式 TEXT/JSON/JSONP/HTML/XML/SCRIPT(服務器返回給客戶端的響應主體中的內容通常是字符串, * 而設置DATA-TYPE='json',jq會內部把獲取的字符串轉化爲JSON格式的對象 => 它不影響服務器返回的結果,只是二次處理結果) * ASYNC:設置是否異步 * CACHE:設置是否緩存,當設置FALSE,而且get請求,JQ會在請求的url地址末尾加隨機數 * SUCCESS:回調函數,當Ajax請求成功執行,JQ執行回調函數時把響應主體中獲取的結果(二次處理)當作參數 * ERROR: 請求失敗後執行的回調函數 */
$.ajax({
url: 'xxx',
method: 'GET',
data: null,
dataType: 'json',
async: true,
cache: true,
success: (result, textStatus, xhr) => {},
error: () => {}
})
複製代碼
~ function (window) {
function AJAX(options) {
return new AJAX.prototype.init(options);
}
function init(options = {}){
let {
url,
method = 'GET',
data = null,
dataType = 'JSON',
async = true,
cache = true,
success,
error
} = options;
//=>MOUNT 把配置項掛載到實例上
['url', 'method', 'data', 'dataType', 'async', 'cache', 'success',
'error'].forEach(item => {
this[item] = eval(item);
});
}
AJAX.prototype = {
constructor: AJAX,
init,
sendAjax(){
this.handleCache();
this.handleData();
//send
let {method, url, async, error, success} = this;
//SEND發送請求
let xhr = new XMLHttpRequest();
xhr.open(method, url, async);
xhr.onreadystatechange = () => {
if(xhr.readyState === 4){
if(!/^(2|3)\d{2}$/.test(xhr.status)){
error && error(xhr.statusText, xhr)
}
//處理DATA-TYPE
let result = this.handleDataType(xhr);
success && success(result, xhr);
}
};
xhr.send();
},
handleDataType(xhr) {
let dataType = this.dataType.toUpperCase(),
result = xhr.responseText;
switch (dataType) {
case 'TEXT':
break;
case 'JSON':
result = JSON.parse(result);
break;
case 'XML':
result = xhr.responseXML;
break;
}
return result;
},
handleCache() {
let {url, method, cache} = this;
if(/^GET$/i.test(method) && cache==false){
url += `${this.check()}=${+(new Date())}`;
}
},
handleData() {
let {data, method} = this;
if(!data) return;
if(typeof data === 'object'){
//若是是一個對象,咱們把它轉換爲x-www-form-urlencoeded模式
for(let key in data){
if(data.hasOwnProperty(key)){
str += `${key}=${data[key]}`;
}
}
data=str.substring(0,str.length);
}
if(/^(GET|DELETE|HEAD|TRACE|OPTIONS)$/i.test(method)){
this.url += `${this.check()}${data}`;
this.data = null;
return;
}
this.data = data; //POST處理方式
},
check() {
return this.url.indexOf('?')>-1?'&':'?';
}
}
init.prototype = AJAX.prototype;
window.ajax = AJAX;
}(window)
複製代碼
~ function (window) {
//設置默認的參數配置項
let _default = {
method: 'GET',
url: '',
baseURL: '',
headers: {},
dataType: 'JSON',
data: null, //POST系列
params: null, //GET系列
cache: true
};
//基於Promise設計模式管理Ajax
let ajaxPromise = function axios() {
let {
url,
baseURL,
data,
dataType,
headers,
cache,
params
} = options;
//=>把傳遞的參數進一步進行處理
if(/^(GET|DELETE|HEAD|OPTIONS)$/.test(method)){
//GET參數
if(params) {
url += `${ajaxPromise.check(url)}${ajaxPromise.formatData(params)}`
}
if(cache === false){
url += `${ajaxPromise.check(url)}_=${+(new Date())}`
}
data= null;//GET系列請求主體爲空
}else{
//POST系列
if(data){
data = ajaxPromise.formatData(data);
}
}
//=>基於Promise發送Ajax
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open(method, `${baseURL}${url}`);
if(headers != null && typeof headers === 'object'){
for(let attr in headers){
if(headers.hasOwnProperty(attr)){
let val = headers[attr];
if(/[\u4e00-\u9fa5]/.test(val)){
val = encodeURIComponent(val);
}
xhr.setRequestHeader(attr, headers[attr]);
}
}
}
//=>若是headers存在,咱們須要設置請求頭
xhr.onreadystatechange = () => {
if (xhr.readyState === 4){
if(/^(2|3)\d{2}$/.test(xhr.status)){
let result = xhr.responseText;
dataType = dataType.toUpperCase();
dataType === 'JSON'?result = JSON.parse(result):(dataType === 'XML'?result = xhr.responseXML : null);
resolve(result, xhr);
return;
}
reject(xhr.statusText, xhr);
}
}
xhr.send(data);
})
}
ajaxPromise.defaults = _default;
ajaxPromise.formatData = function formatData(){
let str = ``;
for(let attr in obj) {
if(obj.hasOwnProperty(attr)){
str += `${attr}=${obj[attr]}&`;
}
return str.substring(0, str.length-1)
}
}
ajaxPromise.check = function check(url){
return url.indexOf('?')>-1?'&':'?';
}
//GET系列
['get', 'delete', 'head', 'options'].forEach(item => {
ajaxPromise[item] = (url, options = {}) => {
options = {
..._default,
...options,
url,
method: item.toUpperCase()
};
return ajaxPromise(options);
}
})
//POST系列
['post', 'put', 'patch'].forEach(item => {
ajaxPromise[item] = (url, data = {}, options = {}) => {
options = {
..._default,
...options,
url,
method: item.toUpperCase(),
data
};
return ajaxPromise(options);
}
})
window.ajaxPromise = ajaxPromise;
}(window)
複製代碼
關於Ajax一點小小的總結,但願對你們有幫助!