jsonp實現數據跨域請求

一、咱們知道,哪怕跨域js文件中的代碼(固然指符合web腳本安全策略的),web頁面也是能夠無條件執行的。javascript

遠程服務器remoteserver.com根目錄下有個remote.js文件代碼以下:php

alert('我是遠程文件');

本地服務器localserver.com下有個jsonp.html頁面代碼以下:html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>

</body>
</html>

毫無疑問,頁面將會彈出一個提示窗體,顯示跨域調用成功java

二、如今咱們在jsonp.html頁面定義一個函數,而後在遠程remote.js中傳入數據進行調用。jquery

jsonp.html頁面代碼以下:web

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript">
    var localHandler = function(data){
        alert('我是本地函數,能夠被跨域的remote.js文件調用,遠程js帶來的數據是:' + data.result);
    };
    </script>
    <script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>

</body>
</html>

remote.js文件代碼以下:ajax

localHandler({"result":"我是遠程js帶來的數據"});

運行以後查看結果,頁面成功彈出提示窗口,顯示本地函數被跨域的遠程js調用成功,而且還接收到了遠程js帶來的數據。很欣喜,跨域遠程獲取數據的目的基本實現了,可是又一個問題出現了,我怎麼讓遠程js知道它應該調用的本地函數叫什麼名字呢?畢竟是jsonp的服務者都要面對不少服務對象,而這些服務對象各自的本地函數都不相同啊?咱們接着往下看。json

三、聰明的開發者很容易想到,只要服務端提供的js腳本是動態生成的就好了唄,這樣調用者能夠傳一個參數過去告訴服務端「我想要一段調用XXX函數的js代碼,請你返回給我」,因而服務器就能夠按照客戶端的需求來生成js腳本並響應了。跨域

看jsonp.html頁面的代碼:安全

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript">
    // 獲得航班信息查詢結果後的回調函數
    var flightHandler = function(data){
        alert('你查詢的航班結果是:票價 ' + data.price + ' 元,' + '餘票 ' + data.tickets + ' 張。');
    };
    // 提供jsonp服務的url地址(無論是什麼類型的地址,最終生成的返回值都是一段javascript代碼)
    var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
    // 建立script標籤,設置其屬性
    var script = document.createElement('script');
    script.setAttribute('src', url);
    // 把script標籤加入head,此時調用開始
    document.getElementsByTagName('head')[0].appendChild(script); 
    </script>
</head>
<body>

</body>
</html>

此次的代碼變化比較大,再也不直接把遠程js文件寫死,而是編碼實現動態查詢,而這也正是jsonp客戶端實現的核心部分,本例中的重點也就在於如何完成jsonp調用的全過程。

咱們看到調用的url中傳遞了一個code參數,告訴服務器我要查的是CA1998次航班的信息,而callback參數則告訴服務器,個人本地回調函數叫作flightHandler,因此請把查詢結果傳入這個函數中進行調用。

OK,服務器很聰明,這個叫作flightResult.aspx的頁面生成了一段這樣的代碼提供給jsonp.html(服務端的實現這裏就不演示了,與你選用的語言無關,說到底就是拼接字符串):

flightHandler({
    "code": "CA1998",
    "price": 1780,
    "tickets": 5
});

咱們看到,傳遞給flightHandler函數的是一個json,它描述了航班的基本信息。運行一下頁面,成功彈出提示窗口,jsonp的執行全過程順利完成!

四、到這裏爲止的話,相信你已經可以理解jsonp的客戶端實現原理了吧?剩下的就是如何把代碼封裝一下,以便於與用戶界面交互,從而實現屢次和重複調用。

什麼?你用的是jQuery,想知道jQuery如何實現jsonp調用?好吧,那我就好人作到底,再給你一段jQuery使用jsonp的代碼(咱們依然沿用上面那個航班信息查詢的例子,假定返回jsonp結果不變):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <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會自動爲你處理數據
//由於請求的是json文件,json不是服務器端的動態語言不能進行解析,若是是php或者其餘的服務器端語言,則不用寫死函數名
success: function(json){ alert('您查詢到航班信息:票價: ' + json.price + ' 元,餘票: ' + json.tickets + ' 張。'); }, error: function(){ alert('fail'); } }); }); </script> </head> <body> </body> </html>

文章部分援引自:【原創】說說JSON和JSONP,也許你會豁然開朗,含jQuery用例