Ajax的深入理解及使用

我們?cè)趯W(xué)習(xí)一個(gè)東西的時(shí)候首先要知道,學(xué)習(xí)的東西是什么,他可以干什么,為什么使用它?

那么到底什么是ajax呢?

AJAX 不是 JavaScript 的規(guī)范,他是一個(gè)老伙計(jì)自創(chuàng)的名字 : Asynchronous JavaScript and XML,意思就是用JavaScript執(zhí)行異步網(wǎng)絡(luò)請(qǐng)求。

他可以干什么呢?

在整個(gè)網(wǎng)頁不重新加載的情況下,更新部分頁面的內(nèi)容。

為什么要使用它呢?

根據(jù)業(yè)務(wù)需求,發(fā)送http請(qǐng)求,拿到服務(wù)端數(shù)據(jù),在頁面上渲染數(shù)據(jù)。

好,言歸正傳,讓我們開始學(xué)習(xí)AJAX

什么是xhr

ajax技術(shù)的核心就在于 XMLHttpRequest 對(duì)象(簡稱xhr),首先由微軟引用,隨后,其他瀏覽器也支持啦該對(duì)象, xhr為向服務(wù)器發(fā)送請(qǐng)求和解析服務(wù)器響應(yīng)提供啦流暢的接口。

IE5中xhr對(duì)象,是通過ActiveX對(duì)象實(shí)現(xiàn)的,IE7+即其他瀏覽器都支持xhr對(duì)象,所以需要寫一個(gè)兼容

// 創(chuàng)建一個(gè)xhr對(duì)象(帶兼容處理)
function create(){
    var xhr = null;
    if(window.XMLHttpRequest){
        xhr = new XMLHttpRequest();
    }else{
        xhr = new ActiveXObject('Microsoft.XMLHTTP')
    }
    return xhr;
}

注意,如果需要多個(gè)請(qǐng)求,就創(chuàng)建多個(gè)xhr對(duì)象,當(dāng)然也可以使用同一個(gè)xhr對(duì)象,但是這回終止xhr對(duì)象之前的異步請(qǐng)求

xhr對(duì)象的方法

open()

在使用xhr對(duì)象,第一個(gè)要調(diào)的方法是open(method,ull,async)

該方法是向服務(wù)器發(fā)送之前做一些設(shè)置,比如你打電話,輸入電話號(hào),然后看看是用卡一還是卡二,

xhr.open('GET','http://www.example.com/api',true)
/*
    第一個(gè)參數(shù)表示使用哪種http請(qǐng)求方法,不區(qū)分大小寫,一般還是寫大寫的,常用的兩個(gè)方法:get()、post()
      get方法用于常規(guī)請(qǐng)求,一般從服務(wù)器讀取數(shù)據(jù)使用該方法
      post方法常用語HTML表單請(qǐng)求,一般向服務(wù)器發(fā)送數(shù)據(jù)使用該方法
    第二個(gè)參數(shù)表示url,要請(qǐng)求的資源地址
    第三個(gè)參數(shù)表示是否異步,true\false
/*

send()

send方法接受一個(gè)參數(shù),即要作為請(qǐng)求主體發(fā)送的數(shù)據(jù),調(diào)用send的方法,請(qǐng)求發(fā)送到服務(wù)器,該方法等于按下?lián)艽虬粹o

如果是GET方法,send()無參數(shù)或?yàn)閚ull;如果是POST方法參數(shù)是要發(fā)送的數(shù)據(jù)

xhr.send('a=1&b=2');

xhr對(duì)象的事件

xhr.onerror

xhr.onerror = function(e){
    console.log(e)
}
// 該事件當(dāng)請(qǐng)求失敗時(shí)觸發(fā)

xhr.ontimeout

xhr.timeout = 1000; // 設(shè)置請(qǐng)求時(shí)間的限制,毫秒為單位,默認(rèn)為0,
xhr.ontimeout = function(){
    alert('請(qǐng)求超時(shí)')
}
// 當(dāng)請(qǐng)求超過指定的時(shí)間時(shí)觸發(fā)

xhr.onprogress

// 監(jiān)聽進(jìn)度事件,如果請(qǐng)求的資源很小,直接就100%
xhr.onprogress = function(e){
    console.log((e.loaded / e.total) * 100 + '%');
}

接收響應(yīng)

先檢測(cè)XHR對(duì)象的readyState屬性,該屬性表示請(qǐng)求/響應(yīng)過程的當(dāng)前活動(dòng)階段。這個(gè)屬性可取的值如下:

0(UNSENT):未初始化。尚未調(diào)用open()方法
1(OPENED):啟動(dòng)。已經(jīng)調(diào)用open()方法,但尚未調(diào)用send()方法
2(HEADERS_RECEIVED):發(fā)送。己經(jīng)調(diào)用send()方法,且接收到頭信息
3(LOADING):接收。已經(jīng)接收到部分響應(yīng)主體信息
4(DONE):完成。已經(jīng)接收到全部響應(yīng)數(shù)據(jù),而且已經(jīng)可以在客戶端使用了

在XHR對(duì)象的 readyState 屬性改變的話會(huì)觸發(fā)XHR對(duì)象的 onreadystatechange 事件,所以我們通常使用onreadystatechange事件監(jiān)聽狀態(tài)的變化

注意:一定要在open之前設(shè)置 onreadystatechange 事件,才能確保跨瀏覽器兼容性,否則將無法接收readyState屬性為0和1的情況

xhr.onreadystatecahnge = function (){
    if(xhr.readyState){
        // another code
    }
}

單單上邊的處理還是不夠的,因?yàn)閤hr.readyState是指運(yùn)行ajax所經(jīng)歷的幾種狀態(tài),所以還需要判斷ajax是否請(qǐng)求成功

一個(gè)完整的HTTP響應(yīng)由狀態(tài)碼、響應(yīng)頭集合和響應(yīng)主體組成。在收到響應(yīng)后,這些都可以通過XHR對(duì)象的屬性和方法使用,主要有以下4個(gè)屬性

responseText: 作為響應(yīng)主體被返回的文本(文本形式)
responseXML: 如果響應(yīng)的內(nèi)容類型是'text/xml'或'application/xml',這個(gè)屬性中將保存著響應(yīng)數(shù)據(jù)的XML DOM文檔(document形式)
status: HTTP狀態(tài)碼(數(shù)字形式)
statusText: HTTP狀態(tài)說明(文本形式)
xhr.onreadystatechange = function(){
    if(xhr.readyState){
        if(xhr.status>= 200 && xhr.status < 300 || xhr.status == 304){
           
        }
    }
}

關(guān)于xhr.status的解釋 : https://baike.baidu.com/item/HTTP%E7%8A%B6%E6%80%81%E7%A0%81/5053660?fr=aladdin

最后上一篇我自己封裝的ajax吧

const ajax = (json) => {
    let xhr = null,
        type = json.type.toUpperCase() || 'GET'; // 設(shè)置請(qǐng)求的默認(rèn)方法
    // 兼容處理
    if(window.XMLHttpRequest){
        xhr = new XMLHttpRequest();
    }else{
        xhr = new ActiveXObject('Microsoft.XMLHTTP')
    }
    // 設(shè)置請(qǐng)求時(shí)間的限制
    xhr.timeout = json.time ? json.time : 0;
    // 設(shè)置請(qǐng)求找過指定時(shí)間的時(shí)間
    xhr.ontimeout = json.timeout ? json.timeout : null;
    // 監(jiān)聽xhr對(duì)象額狀態(tài)
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4){
            if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
                json.success(xhr.responseText) // 如果成功 即調(diào)用成功的回調(diào)函數(shù)
            }else{
                json.error&&json.error() // 失敗調(diào)用失敗的回調(diào)函數(shù)
            }
        }
    }
    if(type.toUpperCase() == 'GET'){
        xhr.open('GET',json.url+'?'+toStr(json.data),true); 
        xhr.send()
    }else if(type.toUpperCase() == 'POST'){
        xhr.open('POST',json.url,true);
        xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
        xhr.send(toStr(json.data))
    }
}
// 將對(duì)象的屬性和value轉(zhuǎn)換為 a:1&b:2
const toStr = json => {
    var arr = [];
    for(var i in json){
        arr.push(i+'='+json[i])
    }
    return arr.join('&')
} 
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容