成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

刨根問底ajax原理與封裝

caige / 1811人閱讀

摘要:所以今天我們就詳細(xì)了解一下的實(shí)現(xiàn)原理和封裝的關(guān)鍵步驟。接下來,我們嘗試自己封裝一個(gè)支持和的簡(jiǎn)易請(qǐng)求。測(cè)試調(diào)用小結(jié)其實(shí)實(shí)現(xiàn)原理并不復(fù)雜,復(fù)雜的是容錯(cuò)兼容性等的處理,使用的時(shí)候盡量使用庫或者框架提供的封裝,避免不必要的漏洞。

說起ajax,大家都不陌生。但是由于目前很多框架或者庫等都對(duì)網(wǎng)絡(luò)請(qǐng)求做了封裝,導(dǎo)致了很多初學(xué)者只知其然而不知其所以然。所以今天我們就詳細(xì)了解一下ajax的實(shí)現(xiàn)原理和封裝ajax的關(guān)鍵步驟。

ajax的核心是XMLHttpRequest對(duì)象。首先我們先創(chuàng)建一個(gè)XMLHTTPRequest對(duì)象 var xhr = new XMLHttpRequest();。

注意:本文所提及的內(nèi)容不兼容古老的IE,有想了解的同學(xué)自行查閱ActiveXObject相關(guān)內(nèi)容。
XMLHttpRequest

在使用XMLHttpRequest對(duì)象的第一步,我們首先要調(diào)用open方法來初始化請(qǐng)求參數(shù),xhr.open("get","/test",true),雖然名字叫open,但是此時(shí)請(qǐng)求還并沒有發(fā)送。

open(method, url[, async, username, password])

method:請(qǐng)求類型,例如GET,POST等

url:請(qǐng)求地址(這里有同源限制,就是我們經(jīng)常會(huì)看到的跨域問題啦)

async:是否發(fā)送異步請(qǐng)求??蛇x參數(shù),默認(rèn)為true。

username&password:可選參數(shù),授權(quán)驗(yàn)證使用的,但是我們一般不這么用,使用后請(qǐng)求變成這個(gè)樣子了,http(s)://username:password@url。

如果調(diào)用了open方法后再次對(duì)它進(jìn)行調(diào)用,則相當(dāng)于調(diào)用了abort方法,abort方法我們?cè)诤竺娼榻B。

如果我們想為為請(qǐng)求綁定一些操作,這個(gè)時(shí)候就可以開始啦。常用的操作有如下幾個(gè):

setRequestHeader(key, value)

顧名思義,這個(gè)方法用于設(shè)置請(qǐng)求頭內(nèi)容。

key:要設(shè)置的請(qǐng)求頭名稱

value:對(duì)應(yīng)請(qǐng)求頭的值

overrideMimeType(type)

重寫服務(wù)器返回的MIME類型。通過這個(gè)方法可以告訴服務(wù)器你想要的數(shù)據(jù)類型。

注意:以上這些操作必須定義在send方法之前。否則,就拿setRequestHeader來說,你都把請(qǐng)求發(fā)出去了再設(shè)置還有什么用?

這個(gè)時(shí)候,我們就可以通過調(diào)用send 方法來發(fā)送請(qǐng)求了,xhr.send(null)

send(data)

發(fā)送請(qǐng)求,如果是同步請(qǐng)求的話,會(huì)阻塞代碼的執(zhí)行,直至收到服務(wù)器響應(yīng)才會(huì)繼續(xù)。

data:發(fā)送給服務(wù)器的數(shù)據(jù)。為了兼容不同的瀏覽器,即使是不需要傳數(shù)據(jù),也需要傳入?yún)?shù)null。

readyStateChanhe()

每次readyState的值改變的時(shí)候都會(huì)觸發(fā)這個(gè)函數(shù)。

getResponseHeader(name)

獲取指定響應(yīng)頭部的值,參數(shù)是響應(yīng)頭部的名稱,并且不區(qū)分大小寫。

getAllResponseHeaders()

獲取服務(wù)器發(fā)送的所有HTTP響應(yīng)的頭部。

在這里我們穿插幾個(gè)概念,readyState,這個(gè)屬性表明了請(qǐng)求的狀態(tài),伴隨HTTP請(qǐng)求的整個(gè)生命周期,它的值表明此時(shí)請(qǐng)求所處的階段,具體如下:

readyState

數(shù)值 描述
0 初始化,open()尚未調(diào)用
1 open()已經(jīng)調(diào)用,但是send未調(diào)用
2 已獲取到返回頭信息
3 正在下載返回體信息
4 請(qǐng)求完成

還有幾個(gè)較為常用的屬性

名稱 含義
responseText 響應(yīng)的文本
status 響應(yīng)的狀態(tài)碼
statusText 響應(yīng)的狀態(tài)信息
responseXML 響應(yīng)內(nèi)容是“text/xml”或者是“application/xml”格式的時(shí)候,這個(gè)屬性的值就是響應(yīng)數(shù)據(jù)的XMLDOM文檔。

我們用下面這段代碼做個(gè)測(cè)試

var xhr = new XMLHttpRequest();
console.log(xhr.readyState)
xhr.onreadystatechange = function(){
    console.log("------")
    console.log("readyState:" + xhr.readyState)
    console.log("ResponseHeaders:" + xhr.getAllResponseHeaders())
    console.log("ResponseText:" + xhr.responseText.length)
    console.log("------")
}
xhr.open("get","/")
xhr.send(null)

下圖我們可以直觀的看到在創(chuàng)建了XMLHttpRequest對(duì)象的時(shí)候,readyState的值為0。


然后我們定義了onreadystatechange函數(shù),讓其打印一些屬性,并調(diào)用open方法,此時(shí)readyState變?yōu)?。


最后我們調(diào)用send方法,可以看到經(jīng)歷了如下過程:

send方法調(diào)用之后,readyState變?yōu)?,此時(shí)responseHeader已經(jīng)獲取到了,responseText為空;

響應(yīng)數(shù)據(jù)開始下載,readyState變?yōu)?

響應(yīng)數(shù)據(jù)下載結(jié)束,readyState變?yōu)?.我們可以發(fā)現(xiàn)此時(shí)responseText的長(zhǎng)度比之前長(zhǎng)。

abort()

取消響應(yīng),調(diào)用這個(gè)方法會(huì)終止已發(fā)送的請(qǐng)求。我們嘗試在之前的代碼最后加一句。

xhr.abort();
console.log(xhr.readyState);


也就是說,send執(zhí)行以后,并沒有去嘗試請(qǐng)求數(shù)據(jù),而是直接取消掉了,并且我們發(fā)現(xiàn)abort會(huì)將readyState的值置為0。

除此之外,XMLHttpRequest還有一個(gè)很重要的屬性withCredentials,cookie在同域請(qǐng)求的時(shí)候,會(huì)被自動(dòng)攜帶在請(qǐng)求頭中,但是跨域請(qǐng)求則不會(huì),除非把withCredentials的值設(shè)為true(默認(rèn)為false)。同時(shí)需要在服務(wù)端的響應(yīng)頭部中設(shè)置Access-Control-Allow-Credentials:true。不僅如此Access-Control-Allow-Origin的值也必須為當(dāng)前頁面的域名。

封裝

到此為止,我們終于講完了XMLHttpRequest的一些常用概念。接下來,我們嘗試自己封裝一個(gè)支持get和post的簡(jiǎn)易jax請(qǐng)求。

function ajax(url, option){
    option = option || {};
    var method = (option.method || "GET").toUpperCase(),
        async = option.async === undefined ? true : option.async,
        params = handleParams(option.data);
    var xhr = new XMLHttpRequest();
    if(async){
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4){
               callback(option,xhr);
            }
        };
    }
    if (method === "GET"){
        xhr.open("GET",url + "?" + params, async);
        xhr.send(null)
    }else if (method === "POST"){
        xhr.open("POST", url, async);
        xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
        xhr.send(params);
    }
    if(!async){
        callback(option,xhr);
    }
    function callback(opt,obj){
        var status = obj.status;
        if (status >= 200 && status < 300 ){
            opt.success && opt.success(obj.responseText,obj.responseXML);
        }else{
            opt.fail && opt.fail(status);
        }
    }
    function handleParams(data) {  
        var arr = [];
        for (var i in data) {
            arr.push(encodeURIComponent(i) + "=" + encodeURIComponent(data[i]));
        }
        return arr.join("&");
    }
}
//  測(cè)試調(diào)用
ajax("/xxx",{
    method:"POST",
    data:{
        key: "test"
    },
    success:function(){
        console.log("success")
    },
    fail:function(){
        console.log("fail")
    }
});
小結(jié)

其實(shí)ajax實(shí)現(xiàn)原理并不復(fù)雜,復(fù)雜的是容錯(cuò)、兼容性等的處理,使用的時(shí)候盡量使用庫或者框架提供的封裝,避免不必要的漏洞。

補(bǔ)充

感謝@蝦嗶嗶的提問,這里做個(gè)簡(jiǎn)單的補(bǔ)充說明。

async是一個(gè)可選的布爾值參數(shù),默認(rèn)為true,意味著是否執(zhí)行異步操作,如果值為false,則send()方法不會(huì)返回任何東西,直到接受到了服務(wù)器的返回?cái)?shù)據(jù)。如果為值為true,一個(gè)對(duì)開發(fā)者透明的通知會(huì)發(fā)送到相關(guān)的事件監(jiān)聽者。這個(gè)值必須是true,如果multipart 屬性是true,否則將會(huì)出現(xiàn)一個(gè)意外。

根據(jù)我的分析,當(dāng)async為false的時(shí)候,readyState會(huì)在send方法之后直接由1變成4。也就是說異步模式,send方法會(huì)立刻返回。同步模式下,只有響應(yīng)完全接受后,send才會(huì)返回。

另外,由于同步模式會(huì)阻塞,較新版本的Chrome在主線程上的同步請(qǐng)求已被棄用。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/95877.html

相關(guān)文章

  • 兩年了,我寫了這些干貨!

    摘要:開公眾號(hào)差不多兩年了,有不少原創(chuàng)教程,當(dāng)原創(chuàng)越來越多時(shí),大家搜索起來就很不方便,因此做了一個(gè)索引幫助大家快速找到需要的文章系列處理登錄請(qǐng)求前后端分離一使用完美處理權(quán)限問題前后端分離二使用完美處理權(quán)限問題前后端分離三中密碼加鹽與中異常統(tǒng)一處理 開公眾號(hào)差不多兩年了,有不少原創(chuàng)教程,當(dāng)原創(chuàng)越來越多時(shí),大家搜索起來就很不方便,因此做了一個(gè)索引幫助大家快速找到需要的文章! Spring Boo...

    huayeluoliuhen 評(píng)論0 收藏0
  • [vuejs 踩坑實(shí)戰(zhàn)系列] 路由場(chǎng)景下父子組件的生命周期順序來個(gè)刨根問底

    摘要:大家中秋假期快樂,假期分享一些原理設(shè)計(jì)文章給大家原創(chuàng)不易,歡迎轉(zhuǎn)發(fā),一起學(xué)習(xí)凌晨寫的,不容易哈,收藏或者點(diǎn)個(gè)贊吧在常見的單頁應(yīng)用中,我們都會(huì)有一個(gè)根文件,里面放置一個(gè)然后配置路由來切換很多人在子父組件嵌套關(guān)系下的生命周期鉤子函數(shù)如何應(yīng)用, 大家中秋假期快樂,假期分享一些原理設(shè)計(jì)文章給大家 原創(chuàng)不易,歡迎轉(zhuǎn)發(fā),一起學(xué)習(xí)(凌晨寫的,不容易哈,收藏或者點(diǎn)個(gè)贊吧) 在常見的單頁應(yīng)用中,我們都...

    FreeZinG 評(píng)論0 收藏0
  • mybatis-plus源碼分析之sql注入器

    摘要:下面我會(huì)詳細(xì)地從源碼的角度分析下文簡(jiǎn)寫成是如何實(shí)現(xiàn)自動(dòng)注入的原理。文件解析器,解析對(duì)應(yīng)的文件信息,并將文件信息注冊(cè)到中。節(jié)點(diǎn)解析器,用于構(gòu)建節(jié)點(diǎn)信息。注冊(cè)與綁定類,將的類信息與綁定。 微信公眾號(hào)「后端進(jìn)階」,專注后端技術(shù)分享:Java、Golang、WEB框架、分布式中間件、服務(wù)治理等等。 老司機(jī)傾囊相授,帶你一路進(jìn)階,來不及解釋了快上車! mybatis-plus是完全基于myba...

    gougoujiang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<