ajax與jsonp一點基礎整理

1、Ajax的概念

  • Ajax是一種技術方案,但並非一種新技術。它依賴的是現有的CSS/HTML/Javascript,而其中最核心的依賴是瀏覽器提供的XMLHttpRequest對象,是這個對象使得瀏覽器能夠發出HTTP請求與接收HTTP響應。
  • Ajax:Asynchronous JavaScript and XML(異步js和XML)javascript

    • 異步js:js的代碼都是至到而下執行的,若是一塊代碼沒有執行完畢,那後面的代碼就不會執行。異步就是ajax能夠作到不按順序執行;
    • ajax不光可以處理XML格式的數據,還能夠處理json、數組、字符串類型的數據;
    • XML:存儲數據的一種格式:
//XML的格式類型;
<name>大力丸</name>
<age>18</age>
<qq>714206204</qq>
<email>daliwan@126.com</email>
  • ajax到底能幹嗎:

js與後端進行數據交互的一種技術,經過請求協商好的接口,來獲取到想要的數據php

  • 優勢

傳輸數據時候會在本頁面請求服務器,不用跳轉頁面,從而減輕服務器壓力。作到實時驗證,減小用戶返工率而且優化用戶體驗java

2、Ajax數據交互流程

  • 建立一個ajax對象;
var val=inputs[0].value;
//下面這個是ajax對象;
var ajax=new XMLHttpRequest;
  • 填寫請求地址;
//open是ajax對象上的一個方法;

ajax.open("get","php/get.php?user="+val,true);

//第一個參數決定是get仍是post方式;
//第二個參數是請求地址,而且把要提交的加上去;
//第三個參數true表明異步,false表明同步;
  • 發送請求;
ajax.send();
  • 等待服務器響應;
ajax.onload=function(){
    //響應好了就接受數據;
    span.innerHTML=ajax.responseText;
}
  • 接收數據;

3、返回的數據類型

ajax.responseText這是服務器返回的值:
1.確定是字符串,有的看起來是對象,實際上是json的形式;ajax

2.用JSON的方法:JSON.parse(aja.responseText)轉成真正的對象就能夠用對象操做的方法去操做了;json

4、XHR的兼容問題

  • XMLHttpRequest是標準瀏覽器下的升級版本,IE6這些瀏覽器不支持;
  • IE6下用ActiveXObject(Microsoft.XMLHTTP)
//寫一個兼容性的函數,實現跨瀏覽器;
var ajax=null;

if(window.XMLHttpRequest){
    ajax=new XMLHttpRequest;
}else{
    ajax=new ActiveXObject(Microsoft.XMLHTTP)
};

5、get和post的區別

  • get方式後端

    • 經過地址欄信息進行數據傳輸,傳輸的大小有限制;
    • 不安全,用戶的全部信息都會暴露出來;
    • 拼接數據的時候要用encodeURI轉一下碼,否則有中文就會亂碼;跨域

      > `encodeURI`把文字轉成符號;

      decodeURI把符號轉成文字;數組

    • 不用設置請求頭;
    • 數據拼接在open方法裏;
    • 會有緩存問題;
  • post方式瀏覽器

    • 經過send向服務器傳輸數據,理論上來講是沒有長度或體積限制;
    • 相對來講安全,由於不直接暴露用戶信息;
    • 不用轉碼,已經經過請求頭設置了數據格式,不會有亂碼;
    • 數據要拼接在send方法裏;
    • 沒有緩存問題
    • 在send()的前面須要設置一個請求頭(不設置要出錯);
ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
//建立對象;
var ajax=null;
if(window.XMLHttpRequest){
    ajax=new XMLHttpRequest;
}else{
    ajax=new ActiveXObject(Microsoft.XMLHTTP)
};
//填寫請求地址;
ajax.open("post","php/post.php",true);
//發送請求,要在send前設置一下請求頭;
ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
ajax.send("user="+val)
//下面的步驟和get方法是同樣的;

6、同步與異步

  • 同步

一、當send()方法調用後會等待服務器返回信息,若是服務器一直沒有響應,就會阻塞後面的代碼,後面的代碼就不會執行
二、後面的代碼執行受前面代碼的影響,前面的代碼沒跑通,後面的代碼就不會執行緩存

  • 異步

一、當send()方法調用後,就會執行後面的代碼,不用等待服務器的響應
二、後面的代碼執行不受前面代碼的影響

7、onreadystatechange與onload

  • ajax.readStateajax的運行步驟(第一步捕捉不到)

    • 它的值爲4的話說明AJAX已經運行完畢;
    • 0 表明初始化,還沒調用open方法;
    • 1 表明載入,已經調用send方法,正在發送請求;
    • 2 表明載入完成,send方法已完成,已收到所有響應內容;
    • 3 表明正在解析響應內容;
    • 4 表明響應完成,能夠在客戶端調用了;
  • ajax.status(狀態碼)

    • 200是成功的;
    • 404是錯誤的;
  • onreadStateChange

readstate的值發生變化就會觸發這個事件;

  • onload

全部請求成功完成後觸發,此時的readstata的值爲4
IE(6,7,8)不支持

如今這個方法逐漸取代onreadstatechange這個方法了

ajax.onreadstatechange=function(){
    if(ajax.readstate==4){          //服務區響應完成了;
        if(ajax.status==200){       //服務器正常;
            //這裏放要執行的代碼;
        }
    }
}

8、封裝ajax函數

封裝ajax函數,傳進函數裏面的參數實際上是一個對象

  • 對象中包包含如下幾種數據,包含在一個對象裏面:

    • URL:發送請求的地址,須要把請求發給誰;
    • method:發送請求的方法:get或者post;
    • dataType:響應以後返回的數據類型:JSON,XML,STRING;
    • data:請求的時候傳的數據(它是一個對象須要處理格式);
    • succ:成功以後的callback;
    • fail:失敗後的callback;
function ajax(json){
    //默認參數;
    var settings={
        url:"",
        method:"get",
        data:{},
        dataType:"json",
        succ:null,
        fail:null
    }
    
    //用戶傳的參數覆蓋默認參數;
    for (var attr in json){
        settings[attr]=json[attr];
    }
    
    //把data拼成正確的格式;
    var arr=[];
    for (var attr in settings.data){
        arr.push(attr+"="+settings.data[attr]);
    }
    settings.data=arr.join("&");
    
    //聲明變量;
    var ajax=window.XMLHttpRequest?new XMLHttpRequest():ActiveXObject("Microsoft.XMLHTTP");
    
    //設置請求方式;
    //請求地址裏面的new Date()方法,是爲了設置不一樣的時間戳去解決緩存的問題;
    if(settings.method.toLocalLowCase==="get"){
        ajax.open("get",settings.url+"?"+settings.data+"&"+new Date().getTime(),true);
        ajax.send();
    }else{
        ajax.open("post",settings.url,true);
        //注意要設置一個請求頭;
        ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
        ajax.send(settings.data);
    }
    
    //設置完成時間的兼容性;IE6下是沒有ajax.onload方法的;
    if(typeof ajax.onload==="undefined"){
        ajax.onreadystatechange=ready;
    }else{
        ajax.onload=ready;
    }
    
    //封裝一個ready()函數;
    function ready(){
        if(ajax.readystate==4){
            if(ajax.status==200){
                //用一個switch判斷返回值得類型;
                switch(settings.dataType.toLocalLowCase()){
                    case "string"   : 
                        settings.succ(ajax.responseText);
                        break;
                    case "json"     :
                        //把responsetext轉成json格式;
                        setting.succ(JSON.parse(ajax.responseText));
                        break;
                    case "xml"      :
                        settings.succ(ajax.responseXml);
                        break;
                }
            }else{
                settings.fail(ajax.status);
            }
        }
    }
}

要注意第57行的JSON.parse在低版本的瀏覽器中是不兼容的,須要下載一個json2.js的文件解決這個問題;

9、ajax上傳

  • 上傳只能用 post 的方法,後臺要處理中文相關的問題;
  • ajax.upload.onprogress 上傳的進度事件;就是上傳的時候要作的事情;

    • ev.loaded 已經上傳的文件大小;
    • ev.total 總的文件大小;

    經過這個能夠作出來一個上傳的進度條;
    用H5中的<progress></progress>這個API;

  • files 上傳的選中的文件列表;

    1.包括文件大小、類型、最後修改的時間等等;

  • FormData 用來建立與表單格式相同的數據,它是XHR的二級定義,是一個二進制的數據;低版本的瀏覽器不支持

**我本身對於FormData的理解:
FormDate能夠new出來一個實例,這個實例能夠繼承它身上的append方法;這個操做放在ajax.openajax.send之間**

var formdata=new FormData();

    //下面經過循環把選中的文件裏面的額東西添加到這個對象身上;

for(var i=0;i<inputs[0].files.length;i++){

    //inputs[0]指的是一個type="file"的表單控件;

    formdata.append("file",inputs[0].files[i]);
}

    //這時候formdata就能夠被髮送給服務器了,前面加上一個請求頭;

10、跨域的問題

  • 概念:

兩個不一樣域名下的數據進行交互。Ajax之因此不能跨域實際上是由於XMLHttpRequest受到同源策略的限制,只能讓它訪問同源下的數據,不能訪問不一樣源下的數據;

  • 同源策略:

每一個網站只能讀取同一來源的數據,這裏的同一來源指的是主機名(域名)、協議(http/https)和端口號的組合。在沒明確受權的狀況下,不能讀寫對方的資源,它是瀏覽器最核心也最基本的安全功能;
只要有一個不同就跨域;

  • 解決跨域的方法:

    • 在標準瀏覽器下XMLHttpRequest配合後端設置一個請求權限,在php裏寫上 header('Access-Control-Allow-Origin:*');
    • 服務器代理,缺點是後端開發的成本大;
    • iframe、flash、postMessage、WebSocket;

這些方法都不是最優的,下面提供一種方法叫作 jsonp

11、jsonp

  • jsonp的概念(json+padding)

    • 經過script標籤引入某些數據,是同步模式的,用script標籤作跨域的時候,不建議將數據提早加載,須要按需加載
    • 當須要數據的時候建立一個script標籤,將須要的數據放在src中,經過onload去監聽是否請求過來,請求完畢就調用傳回來的數據(異步加載);
    • jsonp不能用post請求,只能是get請求;

帶src屬性的<script><img><iframe><link>等標籤是不須要遵照同源策略的,可是經過src加載的資源,瀏覽器限制了javascript的權限,能讀不能寫;這就是jsonp能實現跨域的緣由;

  • jsonp中的回調函數

    • 經過jsonp的方式的數據通常都會放在一個回調函數裏;
    • 請求到的結果是這樣的getData({"color":["red","green","blue"]})

      • 數據放在函數的參數裏,能夠是任何數據形式(對象、數組)
      • 回調函數的名字要麼是後端定死的,要麼是咱們在請求地址跟動態加上的

注意callback是要設置成全局的,要不就放在操做的前面;

  • 封裝一個jsonp
function jsonp(obj){
    var settings={
        url:'',                    //地址
        data:{},                //要發送的數據
        callBack:'callback',    //url裏存儲回調函數名字的變量
        fnName:'jsonp_'+new Date().getTime(),        //回調函數的名字
        succ:function(){}        //請求成功的回調函數
    };
    
    for(var attr in obj){
        settings[attr]=obj[attr];
    }
    
    //建立一個script標籤
    var script=document.createElement("script");
    script.className='sc';
    settings.data[settings.callBack]=settings.fnName;
    
    var head=document.getElementsByTagName('head')[0];
    
    
    //把要傳的數據拼起來
    var arr=[];            //['wd=sds','cb=jQuery1']
    for(var attr in settings.data){
        arr.push(attr+'='+settings.data[attr]);
    }
    settings.data=arr.join('&');
    script.src=settings.url+'?'+settings.data;
    
    head.appendChild(script);
    
    //把回調函數掛載到window身上
    window[settings.fnName]=function(data){
        //當調用這個函數的時候,先把頁面中全部的已經請求過的script刪掉
        var scripts=head.getElementsByTagName('script');
        for(var i=0;i<scripts.length;i++){
            if(scripts[i].className=='sc'){
                head.removeChild(scripts[i]);
            }
        }
        
        settings.succ(data);
    };
}
相關文章
相關標籤/搜索