1.什么是ajax跨域請求
當通過ajax異步請求其他域名的服務時,存在跨域無權限訪問的問題。
此時,可以通過JSONP來實現跨域請求。
2.JSONP原理
ajax異步請求無權限訪問。但我們發現,web頁面調用js文件時不存在跨域問題(如在我們的頁面中引入百度地圖API, <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=e3ZohdqyB0RL98hFOiC29xqh"></script>),總結發現,凡是擁有“src”屬性的標簽都擁有跨域的能力,如<script>,<img>,<iframe>等。
這種非正式的傳輸協議,就是JSONP。JSONP的一個要點是允許客戶端傳一個callback參數給服務器,然后服務器返回數據時會用這個callback參數作為函數名,包裹住JSON數據,返回客戶端,客戶端執行返回函數。
3.JSONP客戶端具體實現
1)直接執行返回函數
本地服務器local.com下有個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" src="http://remote.com/remote.js"></script> </head> <body> </body> </html>
遠程服務器remote.com下有個remote.js文件代碼如下:
alert('我是遠程文件');
運行jsonp.html,會彈出“我是遠程文件”,顯示跨域調用成功。
2)客戶端執行回調函數
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 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文件代碼如下:
localHandler({"result":"我是遠程js帶來的數據"});
運行jsonp.html,會彈出“我是遠程js帶來的數據”,顯示跨域調用成功。
3)客戶端傳遞回調函數
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>
flightResult.aspx的頁面生成了一段這樣的代碼提供給jsonp.html
flightHandler({
"code": "CA1998",
"price": 1780,
"tickets": 5
});
運行jsonp.html,成功彈出提示窗口。
4)JSONP封裝了3)中的代碼,以方便客戶端使用。
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>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>
示例中沒有定義flightHandler函數,但代碼成功運行了。
這是因為jquery自動把success屬性方法作為了回調函數。
4.JSONP總結
由上面的講解可知,ajax和jsonp兩種技術看起來很像,但實質上是完全不同。
5.JSON格式數據優點補充
1)基於純文本,跨平台傳遞簡單
2)javascript原生支持,后台語言幾乎全部支持
3)可讀性強
4)容易編寫和解析