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

資訊專(zhuān)欄INFORMATION COLUMN

JavaScript通信之Ajax

DDreach / 2551人閱讀

摘要:表單提交在中提供了表單提交的功能,我們可以通過(guò)表單把數(shù)據(jù)從前臺(tái)提交到后臺(tái),通過(guò)設(shè)置事件,可以為按鈕或其它元素同樣可以觸發(fā)表單提交的事件賬號(hào)請(qǐng)輸入賬號(hào)密碼請(qǐng)輸入密碼重置重置提交表示獲取頁(yè)面中所有的表單,返回一個(gè)數(shù)組提交成功通過(guò)表單提交數(shù)據(jù)不需

表單提交

在HTML中提供了表單提交的功能,我們可以通過(guò)表單把數(shù)據(jù)從前臺(tái)提交到后臺(tái),通過(guò)設(shè)置submit事件,可以為按鈕或其它元素同樣可以觸發(fā)表單提交的事件


  
賬號(hào):
密碼:
重置:

通過(guò)表單提交數(shù)據(jù)不需要依賴(lài)js引擎,瀏覽器本身就可以實(shí)現(xiàn),但這樣也會(huì)產(chǎn)生一個(gè)問(wèn)題,用戶提交數(shù)據(jù)信息的時(shí)候需要刷新整個(gè)頁(yè)面,這就大大降低了用戶體驗(yàn)

Ajax 什么是Ajax

Ajax的誕生解決了上述的問(wèn)題,Ajax代表的是:Asynchronous Javascript And XML,也就是異步,javascript和XML,Ajax不是一門(mén)編程語(yǔ)言,而是一種用于創(chuàng)建更好更快交互性更強(qiáng)的web應(yīng)用技術(shù),可以通過(guò)少量的瀏覽器和服務(wù)器之間的數(shù)據(jù)交互實(shí)現(xiàn)頁(yè)面的部分刷新,在使用了Ajax技術(shù)后,用戶的請(qǐng)求數(shù)據(jù)是間接通過(guò)Ajax引擎來(lái)發(fā)出的,而不是直接通過(guò)瀏覽器來(lái)發(fā)出,服務(wù)器返回的數(shù)據(jù)也是傳回到Ajax引擎

Ajax雖然在使用時(shí)的優(yōu)點(diǎn)顯而易見(jiàn),但同時(shí)缺點(diǎn)也是存在的:

對(duì)搜索引擎不友好

用戶無(wú)法使用回退獲得之前的頁(yè)面

我們可以對(duì)比一下傳統(tǒng)的提交方式和使用Ajax技術(shù)的提交方式的不同:

Ajax引擎

Ajax的精華部分就是它的Ajax引擎,那么什么是Ajax引擎呢?就是XMLHttpRequest對(duì)象,除了已經(jīng)入土的IE5,其它現(xiàn)代瀏覽器都支持該對(duì)象,同時(shí)它也是一個(gè)JavaScript對(duì)象,它負(fù)責(zé)發(fā)出請(qǐng)求和接收響應(yīng)

在IE5和IE6中Ajax引擎是ActiveXRequest,所以我們可能需要做一下兼容性

使用Ajax 創(chuàng)建Ajax引擎
    function createRequst() {
      return window.XMLHttpRequest ? new window.XMLHttpRequest() :
                    new window.ActiveXObject("Microsoft.XMLHTTP");
    }

    console.log(createRequst());//在IE7-中返回的是一個(gè)object對(duì)象

我們?cè)诳刂婆_(tái)中打印出XMLHttpRequest對(duì)象的方法和屬性

我們找?guī)讉€(gè)比較主要的說(shuō)一下,

onloadstart 請(qǐng)求開(kāi)始時(shí)觸發(fā)的事件

onloadend 請(qǐng)求結(jié)束時(shí)觸發(fā)的事件

ontimeout 請(qǐng)求超時(shí)時(shí)觸發(fā)的事件

onreadystatechange 請(qǐng)求狀態(tài)改變時(shí)觸發(fā)的事件

readyState 請(qǐng)求狀態(tài)

status 服務(wù)器返回的狀態(tài)碼

timeout 設(shè)置請(qǐng)求的時(shí)間,當(dāng)請(qǐng)求的時(shí)間超過(guò)我們?cè)O(shè)置的時(shí)間時(shí),自動(dòng)將請(qǐng)求注銷(xiāo)掉

withCredentials 是否要求證書(shū)(例如12306)

responseText 在非XML格式下返回的數(shù)據(jù)

建立連接
    var xhr=createRequst();//封裝的函數(shù)
    xhr.open("GET","data.php",true);
    //如果是使用GET方式提交數(shù)據(jù)那么需要在URl后添加?然后把鍵值對(duì)之間以&符號(hào)鏈接拼接在?后面
    //如果是使用POST獲取數(shù)據(jù),那么我們要將參數(shù)傳遞到send中,鍵值對(duì)與鍵值對(duì)之間使用&符號(hào)拼接

在建立連接時(shí),我們要調(diào)用open方法,open方法有三個(gè)參數(shù)

open(type,url,isAsync),這幾個(gè)參數(shù)分別代表:

type,請(qǐng)求方式,GET還是POST,當(dāng)然還有其它方式,如DELETE,但不常用,這里不列舉了

url ,請(qǐng)求的服務(wù)器的地址

isAsync ,請(qǐng)求是否異步,默認(rèn)為true,也就是異步請(qǐng)求

GET和POST

這里我們需要了解一下同樣是請(qǐng)求后臺(tái)數(shù)據(jù),GET和POST的區(qū)別,如果只是列舉簡(jiǎn)單的區(qū)別:

GET請(qǐng)求是體現(xiàn)在url地址欄中的,安全性比較差,POST是在request body提交的,安全性較高

GET請(qǐng)求的參數(shù)是會(huì)被保存在地址欄中的,而POST不會(huì),也就是說(shuō)在我們使用后退鍵時(shí),使用GET請(qǐng)求會(huì)保存在地址欄中

使用POST的時(shí)候,如果使用后退鍵會(huì)重復(fù)提交,而GET則不會(huì)

POST方式理論上是沒(méi)有大小的限制的,而GET方式由于瀏覽器會(huì)限制地址欄的長(zhǎng)度,一般限制為2K字符以?xún)?nèi),4K大小以?xún)?nèi),超過(guò)部分不予解析

對(duì)于參數(shù)類(lèi)型,GET方式只支持ASCLL編碼格式,而POST則沒(méi)有限制(使用前最好將傳入的數(shù)據(jù)進(jìn)行編碼轉(zhuǎn)換)

但是,在看到一篇大神的文章之后,以上的區(qū)別統(tǒng)統(tǒng)顯的不重要了,我們來(lái)開(kāi)始學(xué)習(xí)怎樣高逼格的說(shuō)明這倆者的不同

我們都知道,無(wú)論是GET還是POST請(qǐng)求,都是建立在HTTP協(xié)議之上的,而HTTP協(xié)議又是建立在TCP協(xié)議之上的,也就是HTTP協(xié)議規(guī)定的數(shù)據(jù)在萬(wàn)維網(wǎng)中傳輸?shù)牡囊?guī)定,那么說(shuō)白了GET和POST只是兩種不同的TCP鏈接,只是由于瀏覽器的規(guī)定設(shè)置導(dǎo)致了有一些差異,在本質(zhì)上并沒(méi)有什么區(qū)別,實(shí)際上真正的差別在于,GET和POST在傳輸數(shù)據(jù)的過(guò)程中,GET會(huì)產(chǎn)生一個(gè)TCP數(shù)據(jù)包,而POST會(huì)產(chǎn)生兩個(gè)數(shù)據(jù)包

瀏覽器在發(fā)送GET請(qǐng)求時(shí)是將http header和data一起發(fā)出,服務(wù)響應(yīng)200,而在發(fā)送POST請(qǐng)求時(shí)。瀏覽器會(huì)先發(fā)送http header,服務(wù)器響應(yīng)100 continue,再發(fā)送data,服務(wù)器響應(yīng)200,也就是說(shuō),GET方式提交數(shù)據(jù)是一次性的,而POST第一次先告訴服務(wù)器我要請(qǐng)求數(shù)據(jù),第二次再將數(shù)據(jù)提交過(guò)去

所以這里由于POST是兩次請(qǐng)求,耗時(shí)會(huì)增加,這也是雅虎優(yōu)化建議中為什么提出,我們盡量將頁(yè)面中使用POST的方式改為GET來(lái)提升響應(yīng)速度,但是,在網(wǎng)絡(luò)性能好的情況下,使用GET和POST的時(shí)間差別幾乎沒(méi)有,在網(wǎng)絡(luò)較差的情況下,兩次打包會(huì)大大提升數(shù)據(jù)的完整性,而且不是所有瀏覽器都是兩次打包的,F(xiàn)irefox就是使用一次打包

至于安全性方面,GET和POST同樣不安全,通過(guò)POST加密的數(shù)據(jù)會(huì)被抓包工具截取,如果有要求使用加密同樣需要通過(guò)加密方式進(jìn)行加密

監(jiān)聽(tīng)狀態(tài)信息

繼續(xù)上面的栗子:

xhr.onreadystatechange=function(){
      if(xhr.readyState===4){
      //判斷請(qǐng)求狀態(tài)是否是已經(jīng)完成
        if(xhr.status>=200&&xhr.status<=300||xhr.status===304){
        //判斷服務(wù)器是否返回成功200,304
          console.log(xhr.responseText);
          //接收xhr的數(shù)據(jù)
        }
      }
    }

這里有一些需要我們了解的

readyState 請(qǐng)求的狀態(tài)碼

0: 表示請(qǐng)求未初始化,也就是沒(méi)有建立open請(qǐng)求

1: 表示建立open()請(qǐng)求,正在發(fā)送請(qǐng)求

2: 表示請(qǐng)求已經(jīng)接收,open()方法已經(jīng)完成,已經(jīng)收到全部響應(yīng)內(nèi)容

3: 表示請(qǐng)求處理中,正在解析響應(yīng)內(nèi)容

4: 表示請(qǐng)求已經(jīng)完成,響應(yīng)也已經(jīng)就緒,也就是說(shuō)響應(yīng)內(nèi)容已經(jīng)解析完成,可以在客戶端進(jìn)行調(diào)用了

status 服務(wù)器返回的狀態(tài)碼,有幾種常見(jiàn)的類(lèi)型:

以1開(kāi)頭代表請(qǐng)求已經(jīng)接受

以2開(kāi)頭代表請(qǐng)求已經(jīng)成功

200,請(qǐng)求成功

以3開(kāi)頭代表網(wǎng)頁(yè)重定向,常見(jiàn)的幾個(gè):

304,代表瀏覽器緩存可以繼續(xù)使用,服務(wù)器沒(méi)有返回?cái)?shù)據(jù),直接從瀏覽器中獲取數(shù)據(jù)

以4開(kāi)頭代表請(qǐng)求錯(cuò)誤 ,檢查是不是url輸入錯(cuò)誤或者是后臺(tái)人員接口給錯(cuò)了

404,無(wú)法找到指定的資源,也就是url地址錯(cuò)誤

405,請(qǐng)求方法對(duì)請(qǐng)求資源不適用

403,請(qǐng)求不允許

以5開(kāi)頭代表服務(wù)器錯(cuò)誤,需要后臺(tái)人員配合進(jìn)行調(diào)試

如何解決服務(wù)器返回304

瀏覽器有默認(rèn)的緩存機(jī)制,在第一次向服務(wù)器請(qǐng)求數(shù)據(jù)的時(shí)候,在發(fā)現(xiàn)頁(yè)面中存在文件請(qǐng)求時(shí)會(huì)發(fā)出請(qǐng)求,并將這些請(qǐng)求緩存在本地,在第二次向服務(wù)器發(fā)送請(qǐng)求的時(shí)候,在請(qǐng)求頭中發(fā)送一個(gè)Last-Modified,它包含了上一次從服務(wù)器獲得數(shù)據(jù)的日期。如果服務(wù)器判斷從這個(gè)日期起服務(wù)器中數(shù)據(jù)沒(méi)有進(jìn)行修改,那么直接返回304的狀態(tài),不再重新發(fā)送數(shù)據(jù),此時(shí)用戶僅僅是獲取了304狀態(tài)碼,不會(huì)再次請(qǐng)求數(shù)據(jù),而是直接從本地讀取緩存

避免服務(wù)器返回304最簡(jiǎn)單的方法就是直接在url地址中添加一個(gè)隨機(jī)數(shù)的時(shí)間戳,例如:/Home/GetMusic?c_time=時(shí)間戳

在前端有個(gè)設(shè)置可以解決讀取緩存的方法,設(shè)置meta標(biāo)簽的屬性

或者設(shè)置Ajax默認(rèn)禁止緩存

    var xhr=createRequst();//封裝的函數(shù)
    xhr.open("GET","data.php",true); 
    xhr.onreadystatechange=()=>{
      if(xhr.readyState===4){
        if(xhr.status>=200&&xhr.status<=300||xhr.status===304){
          console.log(xhr.responseText);
        }
      }
    }
    xhr.setRequsetHeader("Content-type":"application/x-www-form-urlcoded");
    xhr.setRequsetHeader("Canhe-Control","no-cache");//阻止瀏覽器讀取緩存
    xhr.send();

如果使用jQuery進(jìn)行開(kāi)發(fā),可以在在jQuery中設(shè)置Ajax的cache屬性,該值默認(rèn)為ture,設(shè)置為false即代表禁止瀏覽器緩存

發(fā)送請(qǐng)求頭

在使用POST發(fā)送頁(yè)面的時(shí)候需要注意的是,要發(fā)送請(qǐng)求頭,格式如下:

xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
//設(shè)置請(qǐng)求頭格式為仿照f(shuō)orm表單提交

在發(fā)送Ajax請(qǐng)求時(shí)默認(rèn)發(fā)送的請(qǐng)求頭格式為文本格式,如果用來(lái)提交表單數(shù)據(jù)會(huì)報(bào)錯(cuò),所以需要我們認(rèn)為的設(shè)置請(qǐng)求頭格式,以上的代碼的作用就是告訴服務(wù)器我們發(fā)送的是form表單格式的數(shù)據(jù)

發(fā)送請(qǐng)求
    xhr.send();

這里我們注意一個(gè)問(wèn)題,關(guān)于send()的位置問(wèn)題,之前我們一直把send()放在監(jiān)聽(tīng)事件狀態(tài)onreadystatechange之前,這樣寫(xiě)在默認(rèn)的異步狀態(tài)下是沒(méi)有問(wèn)題的,但如果是在同步的狀態(tài)下看,是會(huì)報(bào)錯(cuò)的,這里涉及到了執(zhí)行順序的問(wèn)題,我們是需要先準(zhǔn)備好怎么樣接收數(shù)據(jù),然后才能對(duì)數(shù)據(jù)進(jìn)行接收

JSON數(shù)據(jù)

json是一種鍵值對(duì)模式的字符串,其中的鍵和值都是用雙引號(hào)進(jìn)行包裹,由于json的輕量和便于使用,現(xiàn)在大部分公司使用的都是json格式的數(shù)據(jù)

var str={"name":"Tom","age",18}//如果值是數(shù)字的話可以不使用雙引號(hào)包裹

具體關(guān)于json的定義可以參考JSON

JSON的方法

在瀏覽器中為我們提供了兩種json數(shù)據(jù)格式轉(zhuǎn)化的方法

JSON.parse(ison),該方法表示將接收到的json數(shù)據(jù)格式轉(zhuǎn)化為對(duì)象格式,需要重點(diǎn)注意的是在使用該方法時(shí),必須是鍵值對(duì)使用雙引號(hào)包裹,所以外層的需要是單引號(hào)

JSON.stringify(object),該方法表示將JavaScript中的對(duì)象轉(zhuǎn)化為json格式的字符串

這里其實(shí)還有一個(gè)方法可以解析json格式的字符串,eval,這個(gè)方法比較特殊,W3C對(duì)它的介紹是,很強(qiáng)大的一個(gè)功能,但是運(yùn)用的很少,這是因?yàn)?b>eval方法本身會(huì)自動(dòng)執(zhí)行字符串中所包含的邏輯語(yǔ)句,所以如果我們使用該方法直接接收沒(méi)有驗(yàn)證過(guò)的返回信息就會(huì)很容易遭到攻擊,例如:

  var str={"name":alert("彈出")};
  var o=eval(str);

在執(zhí)行上述代碼時(shí)會(huì)自動(dòng)彈出alert提示框,因?yàn)樵谑褂?b>eval時(shí)已經(jīng)執(zhí)行了字符串內(nèi)部的邏輯代碼,所以不推薦使用該方法

JQuery中的Ajax使用

在JQuery中對(duì)Ajax方法進(jìn)行了封裝,JQuery的Ajax封裝是非常強(qiáng)大的,在其它框架中也大量借鑒了該方法,下面我們來(lái)看一下在JQuery中是如何使用Ajax的

比較簡(jiǎn)單方法:

      $(function(){
          $("#btn").on("click",function(){
             $.post("02.php",{name:"Tom",age:18},function(data){
                console.log(data)
             },"json")
          })
      })
      //相對(duì)應(yīng)的還有GET和getJSON等其它方法,基本套路都一樣

下面的是我們經(jīng)常用到的,同樣也是在其他框架中被參考的方法$.ajax

      $.ajax({
        type:"get",//設(shè)置請(qǐng)求的方式
        url:"02.php",//設(shè)置請(qǐng)求的地址
        data:{name:"tom",age:18},//設(shè)置發(fā)送的參數(shù)
        dataType:"json",//請(qǐng)求的數(shù)據(jù)類(lèi)型,自動(dòng)轉(zhuǎn)化為對(duì)象
        async:true,//設(shè)置是否異步,默認(rèn)為true
        cache:false,//設(shè)置瀏覽器是否緩存該頁(yè)面,默認(rèn)為true
        timeout:300,//設(shè)置請(qǐng)求超時(shí)時(shí)間
        beforeSend:function(xhr){//請(qǐng)求開(kāi)始前回調(diào)該函數(shù)
          console.log("請(qǐng)求開(kāi)始前");
          //return false  如果在請(qǐng)求開(kāi)始前直接return等于阻止了ajax請(qǐng)求
        },
        success:function(result,status){//請(qǐng)求成功時(shí)回調(diào)該函數(shù),,result代表返回的數(shù)據(jù),status為狀態(tài)描述
          console.log("請(qǐng)求成功了");
        },
        error:function(xhr,status,error){//請(qǐng)求失敗時(shí)回調(diào)該函數(shù),xhr為 XMLHttpRequest對(duì)象,status為錯(cuò)誤信息,error表示捕獲的錯(cuò)誤對(duì)象
          console.log("請(qǐng)求失敗,"+xhr.status);
        }
      })
      //以上只是我們常用的一些方法和參數(shù),JQuery中還封裝了很多其它的方法和參數(shù),包括上面提到的$.get和$.post等方法都是該方法的變種
Ajax的封裝

我們簡(jiǎn)單的模擬一下jQuery對(duì)Ajax的封裝

function formatData(data) {//格式化數(shù)據(jù)的方法
    var ret = [];
    for (var key in data) {
        ret.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key]));
        //有時(shí)候傳入的可能是漢字,所以需要利用encodeURIComponent轉(zhuǎn)化成編碼格式
        //encode方法廢棄了,現(xiàn)在提供的是encodeURLConponent方法
    }

    ret.push(("=" + new Date().getTime()));
    //添加時(shí)間戳,防止獲取緩存的數(shù)據(jù)(http狀態(tài)碼304)
    return ret.join("&");
}

function createRequst() {//創(chuàng)建Ajax引擎對(duì)象
    return XMLHttpRequest() ? new XMLHttpRequest() : new ActiveXObject("Msxml2.XMLHTTP")
}

function jsonp(option) { //jsonP方法
    //判斷用戶傳入的參數(shù)
    if (!option || !option.url || !option.callback) {
        console.error("參數(shù)異常");
        return;
    }
    //如果用戶參數(shù)傳入正確,創(chuàng)建script標(biāo)簽,添加到head標(biāo)簽中
    var scriptElement = document.createElement("script"),
        headElement = document.getElementsByTagName("head")[0];
    headElement.appendChild(scriptElement);

    //注意jsonp創(chuàng)建的函數(shù)是全局函數(shù),為了防止代碼污染,起特定的名字
    var fnName = ("jsonp_" + Math.random()).replace(".", "");
    option.data[option.callback] = fnName;

    //給用戶傳入的向后臺(tái)發(fā)送的data數(shù)據(jù)中添加一個(gè)option.callback屬性,并賦值為我們自定義創(chuàng)建的函數(shù)名,讓后臺(tái)接收我們的函數(shù)名,后臺(tái)才能返回給我們數(shù)據(jù)
    window[fnName] = function (data) {
        if (option.timeout) {//用戶如果設(shè)置了超時(shí)時(shí)間,在接收到數(shù)據(jù)后將計(jì)時(shí)器清除
            window.clearTimeout(scriptElem.timer);
        }
        delete    window[fnName];//刪除全局函數(shù)
        headElement.removeChild(scriptElem);//刪除創(chuàng)建的script標(biāo)簽
        option.success && option.success(data);
    }
    if (option.timeout) {//如果用戶設(shè)置了超時(shí)時(shí)間,設(shè)置計(jì)時(shí)器,在用戶設(shè)置的超時(shí)時(shí)間到達(dá)后如果該函數(shù)執(zhí)行,說(shuō)明超時(shí),那么執(zhí)行其中的代碼
        scriptElement.timeout = window.setTimeout(function () {
            delete global[fnName];
            headElem.removeChild(scriptElem);
            option.fail && option.fail({"message": "請(qǐng)求超時(shí)"});
        }, option.timeout)
    }
    scriptElem.src = option.url + "?" + formatData(option.data);//執(zhí)行跨域請(qǐng)求,跨域的時(shí)候不需要其它參數(shù),所以data中的數(shù)據(jù)就是callback和它的值
}

$.extend({
    AjaxSetting: {//設(shè)置用戶默認(rèn)輸入的各項(xiàng)參數(shù)
        url: "",
        type: "GET",
        dataType: "json",
        async: true,
        success: null,//成功后執(zhí)行的函數(shù)
        fail: null,//失敗后執(zhí)行的的函數(shù)
        contentType: "application/x-www-form-urlencoded;charset=UTF-8"http://模擬表單提交的請(qǐng)求頭

    },
    ajax: function (url, option) {//在JQuery中使用的兩個(gè)參數(shù),這里仿照J(rèn)Query寫(xiě)法

        var context, xhr;

        if (typeof url === "object") {//判斷url類(lèi)型,如果用戶直接傳入一個(gè)對(duì)象,說(shuō)明沒(méi)有多帶帶傳入U(xiǎn)RL地址,那么我們執(zhí)行下面的代碼
            option = url;
            url = null;
        } else {//如果用戶多帶帶傳入了url地址,那么我們執(zhí)行下面的代碼
            option.url = url;
            url = undefined;
        }

        if (!option || !option.url || !option.success) {//判斷用戶是否輸入option,option中的url和success是我們?cè)O(shè)置為默認(rèn)必須的,所以在用戶傳入時(shí)就進(jìn)行判斷
            console.error("參數(shù)傳入異常");
            return;
            //如果用戶傳入的參數(shù)異常,那么我們彈出異常,并且直接返回
        }
        // 通過(guò)JQuery中的extend方法獲取默認(rèn)設(shè)置
        $.extend($.AjaxSetting, context);
        // 通過(guò)JQuery中的extend方法獲取用戶設(shè)置,覆蓋或新增默認(rèn)的設(shè)置
        $.extend(option, context);

        if (context.dataType.toLowerCase() === "jsonp") {//判斷用戶是否要求跨域
            jsonp(context);//如果是的話執(zhí)行jsonp的方法
        } else {//否則的話執(zhí)行Ajax函數(shù)
            xhr = createRequst();//通過(guò)createReqyst方法執(zhí)行函數(shù)
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4) {
                    if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
                        var data = context.dataType.toLowerCase() == "json" ?
                            JSON.parse(xhr.responseText) :
                            xhr.responseText;
                        //判斷用戶需求什么格式的數(shù)據(jù),如果是json的數(shù)據(jù),將請(qǐng)求來(lái)的數(shù)據(jù)進(jìn)行轉(zhuǎn)換
                        context.success && context.success(data, context, xhr);
                        //判斷用戶是否輸入了success方法,如果有的話執(zhí)行success方法,如果我們直接執(zhí)行的                          話,由于上面設(shè)置了success為null,用戶如果沒(méi)有設(shè)定會(huì)報(bào)錯(cuò)
                    }
                } else {
                    context.fail && context.fail({"message": "請(qǐng)求超時(shí)."})
                }
            }
            if (context.type.toUpperCase() == "GET") {
                xhr.open("GET", context.url + "?" + formatData(context.data), context.async);
                //利用formatData方法格式化數(shù)據(jù)
                xhr.send();
            } else {
                xhr.open("POST", context.url, context.async);
                xhr.setRequestHeader("contentType", context.contentType)
                xhr.send(formatData(context.data));
            }
        }
    }
})
Ajax輪詢(xún)和長(zhǎng)連接

Ajax輪詢(xún)和長(zhǎng)連接都是為了實(shí)現(xiàn)頁(yè)面的實(shí)時(shí)刷新,但是需要注意,如果在不是必要的情況下盡量不要使用這兩種方法,大量的不間斷的數(shù)據(jù)請(qǐng)求對(duì)前臺(tái)和后臺(tái)都是非常有壓力的,如果要實(shí)現(xiàn)頁(yè)面的實(shí)時(shí)刷新,建議使用WebSocket

Ajax輪詢(xún)

客戶端定時(shí)向服務(wù)器發(fā)送Ajax請(qǐng)求,服務(wù)器在返回?cái)?shù)據(jù)后斷開(kāi)連接,輪詢(xún)能夠?qū)崿F(xiàn)頁(yè)面的實(shí)時(shí)刷新,但是缺點(diǎn)也很明顯,定時(shí)的發(fā)送數(shù)據(jù)大部分是沒(méi)有意義的,而且占用額外的服務(wù)器資源

  
    function Ajax(){
        setInterval(function(){
             var xhr=new XMLHttpRequest();
                 xhr.open("open","url",true);
                 xhr.onreadystatechange=function(){
                     if(xhr.readyState===4){
                         if(xhr.status>=200&&xhr.status<=300||xhr.status==304){
                             console.log(xhr.responseText)
                         }
                     }
                 };
                 xhr.setRequestHeader("Content-type","qpplication/x-www-form-urlencoded");

            },5000)
        }    
  

代碼實(shí)際上很簡(jiǎn)單,就是調(diào)用計(jì)時(shí)器,每過(guò)一段時(shí)間向后臺(tái)發(fā)送一次請(qǐng)求

long-polling

所以為了能夠使頁(yè)面及時(shí)刷新,并且改善輪詢(xún)存在的弊端,我們一般使用的是長(zhǎng)輪詢(xún)的方法,也就是ling-poling

    $(function(){
        (function longPolling(){
            $.ajax({
                url:"01.php",
                type:"get",
                datatype:"json",
                timeout:5000,
                error:function(xml,status,eror){
                     //可以選擇報(bào)請(qǐng)求超時(shí)的錯(cuò)誤,不過(guò)一般不這么做
                     longPolling();
                     
                },
                success:function(data,status,xhr){
                    console.log(data);
                    //如果有數(shù)據(jù)返回,那么將數(shù)據(jù)添加到頁(yè)面
                    longPolling();
                }
            })
        })()
    })

Ajax長(zhǎng)輪詢(xún)需要后臺(tái)寫(xiě)相應(yīng)的代碼來(lái)配合完成,實(shí)際代碼也就是無(wú)論成功或者失敗都再次調(diào)用自身來(lái)向后臺(tái)發(fā)起請(qǐng)求

模板引擎

什么是模板引擎,說(shuō)白了就是在字符串中有幾個(gè)變量待定,我們可以用來(lái)配合Ajax請(qǐng)求返回的數(shù)據(jù)來(lái)動(dòng)態(tài)填充頁(yè)面內(nèi)容,例如:

//這里用到的是attTemplate模板引擎

我們可以在寫(xiě)一個(gè)完整的:




  
  Document
  //導(dǎo)入模板引擎js文件
  




封裝方法主要是使用了string的方法和正則進(jìn)行匹配,下面寫(xiě)一下大概的封裝

    function template(templateStr,data){//傳入兩個(gè)值,templateStr代表模板的字符串,data代表傳入的變量對(duì)象

        var reg = /<%=s*([^%>]+S)s*%>/,//定義正則匹配<%= %>
            result;

        while(result=reg.exec(templateStr)){//根據(jù)正則的exec方法的屬性如果沒(méi)有符合的返回null來(lái)確定循壞停止的條件

            var matchString=result[0],//根據(jù)exec方法返回的是<%= %>這部分的字符串

                matchWord=result[1];//根據(jù)exec方法返回的是<%= %>中的字符,也就是我們傳入的data中的鍵

            templateStr=templateStr.replace(matchString,data[matchWord]);
            //調(diào)用字符串的rplace方法,符合的目標(biāo)進(jìn)行替換
        }
        return templateStr;
    }     
跨域 什么是跨域

出于安全性的考量,現(xiàn)代所有的瀏覽器都遵循同源策略,同源策略不允許Ajax獲取其它網(wǎng)站的數(shù)據(jù),我們通過(guò)某種方式來(lái)獲取其它網(wǎng)頁(yè)的數(shù)據(jù)的方式就是跨域

同源策略

簡(jiǎn)單來(lái)說(shuō)就是在兩個(gè)網(wǎng)頁(yè)域名,端口,協(xié)議任意不同的情況下,A網(wǎng)頁(yè)無(wú)法獲取B網(wǎng)頁(yè)的數(shù)據(jù),舉一個(gè)例子來(lái)說(shuō)明:

http://www.example.com/dir/page.html
http://www.example.com/dir2/other.html  //同源
http://example.com/dir/other.html    //不同源,域名不同
http://v2.www.example.com/dir/other.html    //不同源,域名不同
http://www.example.com:81/dir/other.html    //不同源,端口不同

注意,同一域名下的不同服務(wù)器獲取數(shù)據(jù)也是跨域,例如兩臺(tái)電腦的IP地址不同,A不能直接獲取B電腦服務(wù)器的數(shù)據(jù)

如果是非同源那么會(huì)受到以下限制

cookie, localStorage和indexDB無(wú)法讀取

DOM無(wú)法獲取

AJAX請(qǐng)求可以發(fā)送,但是無(wú)法獲取響應(yīng)

具體的內(nèi)容可以參考:同源策略
?

跨域的方式 JSONP

什么是JSONP,很多人會(huì)把jsonp和Ajax搞混,或者認(rèn)為jsonp是Ajax提供的跨域方法,但特別需要注意,這兩者是相互獨(dú)立的,這里引用一段知乎的回答

jsonp的本質(zhì)可以認(rèn)為是由于src屬性不受同源策略的限制,可以獲取其它域的數(shù)據(jù),利用src能夠跨域獲取數(shù)據(jù)的特性來(lái)實(shí)現(xiàn)我們從其它的網(wǎng)站獲取數(shù)據(jù),前提是必須在該網(wǎng)站配合下

實(shí)際在之前的很多操作中我們已經(jīng)使用到了src能夠跨域的這個(gè)特性,例如我們?cè)趇mg中插入一張圖片,可以直接把圖片的地址復(fù)制到src中

?

所以需要注意,src這個(gè)屬性實(shí)際上是等同于發(fā)送了一個(gè)GET形式的Ajax請(qǐng)求,包括href,所以我們?cè)陧?yè)面中盡量不要寫(xiě)空的hrefsrc屬性,可以減小服務(wù)器的壓力

下面我們來(lái)舉一個(gè)jsonP跨域的例子:


在JQ中為我們封裝了跨域的方法,有兩種方式:

1.$.ajax()方法

2.getJson方式
window.name

在一個(gè)window的存活周期下,窗口載入的所有頁(yè)面都共享一個(gè)window.name屬性,每個(gè)頁(yè)面都對(duì)它有可讀可寫(xiě)的權(quán)限,即使window.location重載也不會(huì)有變化

window.name的格式為字符串,更多的時(shí)候我們使用json的格式來(lái)進(jìn)行書(shū)寫(xiě),window.name存在字符串的限制,最大的大小為2M

下面我們來(lái)舉一個(gè)栗子:

a.html

  
      
      
  

b.html

  
      
  
window.postMessage

這個(gè)方法和window.name一樣,需要是同一個(gè)頁(yè)面打開(kāi)的窗口

我們直接來(lái)舉一個(gè)栗子:

//數(shù)據(jù)端發(fā)送

//數(shù)據(jù)端接收
后臺(tái)轉(zhuǎn)換

這個(gè)方法是實(shí)際工作中最常用的,我們?nèi)绻行枰缬蛘?qǐng)求數(shù)據(jù),一般會(huì)讓后臺(tái)配合請(qǐng)求到數(shù)據(jù)然后在返回給前臺(tái)使用

core

這個(gè)后面再說(shuō)

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

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

相關(guān)文章

  • JavaScriptweb通信

    摘要:設(shè)置一個(gè)定時(shí)器,定時(shí)詢(xún)問(wèn)服務(wù)器是否有信息,每次建立連接傳輸數(shù)據(jù)之后,鏈接會(huì)關(guān)閉。通過(guò)調(diào)用此程序提供的套接口接口與服務(wù)器端的套接口進(jìn)行通信。 本文同步自我的博客園:http://hustskyking.cnblogs.com P.S: 各個(gè)平臺(tái)中就 segmentFault 寫(xiě)博客體驗(yàn)最好了! web通信,一個(gè)特別大的topic,涉及面也是很廣的。因最近學(xué)習(xí)了 javascript 中...

    Honwhy 評(píng)論0 收藏0
  • JavaScript Ajax與Comet——“其他跨域技術(shù)”的注意要點(diǎn)

    摘要:由兩部分組成回調(diào)函數(shù)和數(shù)據(jù)。回調(diào)函數(shù)是當(dāng)響應(yīng)到來(lái)時(shí)應(yīng)該在頁(yè)面中調(diào)用的函數(shù),回調(diào)函數(shù)的名字一般是在請(qǐng)求中指定的。下面是以個(gè)的例子回調(diào)函數(shù)的名字就是是通過(guò)動(dòng)態(tài)的元素來(lái)使用的,使用時(shí)可以為屬性指定一個(gè)跨域。是為與其他傳遞消息的很相似。 圖像Ping技術(shù) 根據(jù)一個(gè)網(wǎng)頁(yè)可以從任何網(wǎng)頁(yè)中加載圖像而不用擔(dān)心使用跨域的原理, 我們可以動(dòng)態(tài)的創(chuàng)建圖像, 使用他們的onload和onerror事件處理程序...

    Hwg 評(píng)論0 收藏0
  • 前端相關(guān)大雜燴

    摘要:希望幫助更多的前端愛(ài)好者學(xué)習(xí)。前端開(kāi)發(fā)者指南作者科迪林黎,由前端大師傾情贊助。翻譯最佳實(shí)踐譯者張捷滬江前端開(kāi)發(fā)工程師當(dāng)你問(wèn)起有關(guān)與時(shí),老司機(jī)們首先就會(huì)告訴你其實(shí)是個(gè)沒(méi)有網(wǎng)絡(luò)請(qǐng)求功能的庫(kù)。 前端基礎(chǔ)面試題(JS部分) 前端基礎(chǔ)面試題(JS部分) 學(xué)習(xí) React.js 比你想象的要簡(jiǎn)單 原文地址:Learning React.js is easier than you think 原文作...

    fuyi501 評(píng)論0 收藏0
  • AJAX 簡(jiǎn)單講解

    摘要:提供一系列新事件,在中我們一般只應(yīng)用,然后檢查狀態(tài)值再?zèng)Q定下一步操作,提供回調(diào)函數(shù)簡(jiǎn)化了這一步驟,在接收完數(shù)據(jù)的時(shí)候即可觸發(fā)。的事件的回調(diào)函數(shù)的事件參數(shù)有兩個(gè)重要屬性和,用來(lái)計(jì)算百分值。不具備對(duì)象及其事件方法。 AJAX(Asynchronous Javascript And XML:異步JavaScript和XML) AJAX 已經(jīng)是老生常談的話題了,它最早起源于1997年,由 Mi...

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

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

0條評(píng)論

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