天天看點

XMLHttpRequest的同域請求和跨域請求以及jsonpXMLHttpRequest的同域請求和跨域請求以及jsonp使用XMLHttpRequestxhr同域請求xhr跨域請求jsonp

XMLHttpRequest的同域請求和跨域請求以及jsonp

  • XMLHttpRequest的同域請求和跨域請求以及jsonp
  • 使用XMLHttpRequest
  • xhr同域請求
      • get
      • post
  • xhr跨域請求
  • jsonp

使用XMLHttpRequest

先建立一個xhr對象,下面代碼是js進階程式設計裡面給出的相容性代碼

function createXHR() {
        if(typeof XMLHttpRequest != "undefined"){
            return new XMLHttpRequest();
        }else if(typeof ActiveXObject != "undefined"){
            if(typeof arguments.callee.activeXString != "string"){
                var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"];

                for(var i=, len=versions.length;i < len; i++){
                    try{
                        var xhr = new ActiveXObject(versions[i]);
                        arguments.callee.activeXString = versions[i];
                        return xhr;
                    }catch(ex){
                            //跳過
                    }
                }
            }
            return new ActiveXObject(arguments.callee.activeXString);
        }else{
            throw new Error("NO XHR object available");
        }
}
var xhr = createXHR();
           

xhr同域請求

同域請求下,服務端不需要做多餘的配置即可使用

統一使用php作為服務端,傳回下列資訊

if(isset($_POST['id']) && !empty($_POST['id'])){
    echo json_encode(array("code" => , "msg" => "success", "id" => $_POST['id']));
    //{"code":1,"msg":"success","id":1}
}else if(isset($_GET['id']) && !empty($_GET['id'])){
    echo json_encode(array("code" => ,"msg" => "success", "id" => $_GET['id']));
    //{"code":1,"msg":"success","id":1}
}else{
    echo json_encode(array("code" => ,"msg" => "fail"));
    //{"code":1,"msg":"fail"}
}
           

get

get方法的用戶端

xhr.onreadystatechange = function () {
    if(xhr.readyState === ){
        if((xhr.status >=  && xhr.status < ) || xhr.status === ){
            alert(xhr.responseText);
        }else{
            alert("Response wa unsuccessful: " + xhr.status);
        }
    }
};
xhr.open('GET', "./jsonp.php?id=1", true); //異步請求
xhr.send(null); //有些浏覽器是必須填null
           

post

xhr.onreadystatechange = function () {
    if(xhr.readyState === ){
        if((xhr.status >=  && xhr.status < ) || xhr.status === ){
            alert(xhr.responseText);
        }else{
            alert("Response wa unsuccessful: " + xhr.status);
        }
    }
};
xhr.open('POST', "./jsonp.php", true); //異步請求
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");//post請求增加的
xhr.send("id=1");
           

xhr跨域請求

跨域請求即請求不同在一個域名上的請求,這裡我開啟了兩個apache伺服器端口來測試,xhr請求檔案放在localhost:8008上面,php服務端放在localhost:80上面

xhr跨域請求主要是多了一個origin的header,而這部分主要在php服務端上進行設定就好,用戶端的js腳本其實和同域請求并無太大差別

其中第一個是必選的

header('Access-Control-Allow-Origin:http://localhost:8008');//設定允許通路的域
header('Access-Control-Allow-Credentials: true');//設定是否發送cookie,需要在用戶端同時設定才會生效
header('Access-Control-Allow-Headers:X-Requested-With');//允許的通路頭部,也需要在用戶端同時設定,同時為了避免跨域通路出錯,用戶端最好不要設定該項資訊,避免服務端不允許
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE');//支援的請求方式
           

用戶端

這裡網上說了有簡單跨域和複雜跨域,差別主要在請求方式和參數設定上,我就不說了,主要是我也還沒了解透,可以看看利用CORS實作跨域請求

//直接是post請求
var url = "http://localhost/jsonp.php"; //我們這裡的用戶端代碼運作在localhost:8008
xhr.open('POST', url, true);
xhr.withCredentials = true; //設定傳遞cookie,如果不需要直接注釋就好
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); //請求頭部,需要服務端同時設定
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send("id=1");
           

以上就是cors跨域的小小執行個體,可以看出cors跨域支援多種請求方式

jsonp

jsonp應該是第一代的跨域請求解決方案了,它的解決思路是利用

script

标簽上的

src

屬性不受跨域影響的特性解決了,就像

img

标簽也不受跨域影響,然後

script

會請求一個服務端程式,服務端程式可以是任意語言,需要的隻是傳回一個使用js回調函數的字元串即可

由于用戶端的回調函數名是在用戶端定義的,是以服務端就必須傳回與用戶端的回調函數一緻的函數名,為了實作動态加載的目的

php這樣寫

$callback = $_GET['callback'];
 $code = $_GET['code'];
 echo $callback."({'code':'".$code."','price':1780,'tickets':5})";
 //回調函數名({'code':'傳遞的參數','price':,'tickets':})
           

用戶端js

// 得到航班資訊查詢結果後的回調函數
    var flightHandler = function(data){
        alert('你查詢的航班結果是:票價 ' + data.price + ' 元,' + '餘票 ' + data.tickets + ' 張。');
    };
    // 提供jsonp服務的url位址(不管是什麼類型的位址,最終生成的傳回值都是一段javascript代碼)
    var url = "http://localhost/jsonp.php?code=CA1998&callback=flightHandler";
    // 建立script标簽,設定其屬性
    var script = document.createElement('script');
    script.setAttribute('src', url);
    // 把script标簽加入head,此時調用開始
    document.getElementsByTagName('head')[].appendChild(script);
           

使用jquery實作jsonp

$.ajax({
    type: "get",
    url: "http://localhost/jsonp.php?code=CA1998",
    dataType: "jsonp",
    jsonp: "callback",//傳遞給請求處理程式或頁面的,用以獲得jsonp回調函數名的參數名(一般預設為:callback)
    jsonpCallback:"flightHandler",//自定義的jsonp回調函數名稱,預設為jQuery自動生成的随機函數名,也可以寫"?",jQuery會自動為你處理資料
    success: function(json){
        alert('您查詢到航班資訊:票價: ' + json.price + ' 元,餘票: ' + json.tickets + ' 張。');
    },
    error: function(){
        alert('fail');
    }
});
           

可以看到jsonp的實作方式其實很簡單,但它的功能有一定的限制,配置項也沒有cors的豐富,最重要的是jsonp隻能發送GET請求,而cors可以發送GET或POST以及其他的請求

繼續閱讀