1. 程式人生 > >解決ajax跨域問題(1)jsonp

解決ajax跨域問題(1)jsonp

https://www.cnblogs.com/ccorz/p/5969737.html

前言

由於瀏覽器存在同源策略的機制,所謂同源策略就是阻止從一個源(域名,包括同一個根域名下的不同二級域名)載入的文件或者指令碼獲取/或者設定另一個源載入的文件屬性.

但比較特別的是:由於同源策略是瀏覽器的限制,所以請求的響應和傳送是可以進行的,只不過瀏覽器不支援罷了.

同源策略限制

瀏覽器的同源策略並不是對所有的請求都有限制的:

  • 限制:XmlHttpRequest
  • 不限制:img iframe script等等具有src屬性的標籤

利用src屬性標籤實現跨域請求

基本思路

利用script標籤,src匯入目標域名的介面,在文件數的head標籤中新增一行script標籤,得到內容後將scprit標籤刪除,返回的解析後的引數即為得到的資料.

利用script標籤實現跨域程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>Index</h1>

    <input type="button" onclick="Ajax();" value="普通AJax"/>
    <input type="button" onclick="Ajax2();" value="跨域普通AJax"/>
    <input type="button" onclick="Ajax3();" value="跨域牛逼AJax"/>
    <input type="button" onclick="Ajax4();" value="江西TV"/>

    <script src="/static/jquery-2.1.4.min.js"></script>
    <script>
            // 原生ajax,測試無效
        function Ajax(){
            $.ajax({
                url: '/get_data/',
                type: 'POST',
                data: {'k1': 'v1'},
                success: function (arg) {
                    alert(arg);
                }
            })
        }
            // 使用ajax跨域請求,測試無效
        function Ajax2(){
            $.ajax({
                url: 'http://wupeiqi.com:8001/api/',
                type: 'GET',
                data: {'k1': 'v1'},
                success: function (arg) {
                    alert(arg);
                }
            })
        }
        
        // 利用script標籤,得到資料
        function Ajax3(){
            // script
            // alert(api)
            var tag = document.createElement('script');
            tag.src = 'http://wupeiqi.com:8001/api/';
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }
        function fafafa(arg){
            console.log(arg);
        }
        
        // 例子,獲取江西衛視的節目單
        function Ajax4(){
            // script
            // alert(api)
            var tag = document.createElement('script');
            tag.src = 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403';
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }
        function list(arg){
            console.log(arg);
        }
    </script>
</body>
</html>

JSONP實現ajax跨域

以上的程式碼其實也是jsonp的基本思路

基本的jsonp寫法

$.ajax({
    url:..
    type: 'GET',
    dataType: 'jsonp',
    //傳遞給請求處理程式或頁面的,用以獲得jsonp回撥函式名的引數名(一般預設為:callback)
    jsonp: 'callback',
    //自定義的jsonp回撥函式名稱,預設為jQuery自動生成的隨機函式名,也可以寫"?",jQuery會自動為你處理資料
    jsonpCallback: 'list'
})
    
function list(arg){
    
}

解釋:

jsonp: callback      #傳送給請求處理程式的,被請求端通過request.GET.get("callback"),獲得jsonp回撥函式的引數

jsonpCallback: 'list' #定義回撥函式的名稱,然後後面通過list(...)來處理獲取資料

生產示例

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="button" onclick="Jsonp1();"  value='提交'/>
    </p>

    <p>
        <input type="button" onclick="Jsonp2();" value='提交'/>
    </p>

    <script type="text/javascript" src="jquery-1.12.4.js"></script>
    <script>
        function Jsonp1(){
            var tag = document.createElement('script');
            tag.src = "http://c2.com:8000/test/";
            document.head.appendChild(tag);
            document.head.removeChild(tag);

        }

        function Jsonp2(){
            $.ajax({
                url: "http://c2.com:8000/test/",
                type: 'GET',
                dataType: 'JSONP',
                success: function(data, statusText, xmlHttpRequest){
                    console.log(data);
                }
            })
        }


    </script>
</body>
</html>

###基於JSONP實現跨域Ajax - Demo

JSONP不能傳送POST請求

究其根源,通過script標籤的src屬性進行跨域請求,<script src='http://www.jxntv.cn/data/jmd-jxtv2.html?callback=qwerqweqwe&_=1454376870403'>最後全部都會轉換成GET請求,哪怕是你把type改為POST.

別處copy的例子,供參考

<html xmlns="http://www.w3.org/1999/xhtml" >
 <head>
     <title>Untitled Page</title>
      <script type="text/javascript" src=jquery.min.js"></script>
      <script type="text/javascript">
     jQuery(document).ready(function(){ 
        $.ajax({
             type: "get",
             async: false,
             url: "http://flightQuery.com/jsonp/flightResult.aspx?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');
             }
         });
     });
     </script>
     </head>
  <body>
  </body>
 </html>

其他ajax跨站請求方式

需要順帶提一句的是,跨站請求還有另一種方式:cors,跨站資源共享,但此中方式對瀏覽器版本有要求,IE8以下的均不支援.

CORS與JSONP相比,無疑更為先進、方便和可靠。

    1、 JSONP只能實現GET請求,而CORS支援所有型別的HTTP請求。

    2、 使用CORS,開發者可以使用普通的XMLHttpRequest發起請求和獲得資料,比起JSONP有更好的錯誤處理。

    3、 JSONP主要被老的瀏覽器支援,它們往往不支援CORS,而絕大多數現代瀏覽器都已經支援了CORS(這部分會在後文瀏覽器支援部分介紹)。