JSONP是一個非官方的協議,它容許在服務器端集成Script tags返回至客戶端,經過javascript callback的形式實現跨域訪問(這僅僅是JSONP簡單的實現形式)。javascript
同源策略限制java
同源策略限制:出於安全方面的考慮,瀏覽器阻止代碼得到或者更改從另外一個域名下得到的文件或者信息。也就是說咱們的請求地址必須和當前網站的地指相同。同源策略經過隔離來實現對資源的保護。這個策略的歷史很是悠久從Netscape Navigator 2.0時代就開始了。ajax
簡單的來講,頁面中的JavaScript沒法訪問其餘服務器上的數據,即「同源策略」。而跨域就是經過某些手段來繞過同源策略限制,實現不一樣服務器之間通訊的效果。json
在同源策略下,在某個服務器下的頁面是沒法獲取到該服務器之外的數據的,但img、iframe、script等標籤是個例外,這些標籤能夠經過src屬性請求到其餘服務器上的數據。利用script標籤的開放策略,咱們能夠實現跨域請求數據,固然,也須要服務端的配合。當咱們正常地請求一個JSON數據的時候,服務端返回的是一串JSON類型的數據,而咱們使用JSONP模式來請求數據的時候,服務端返回的是一段可執行的JavaScript代碼。跨域
具體流程以下:瀏覽器
1. 首先在客戶端註冊一個callback, 而後把callback的名字傳給服務器。
2. 此時,服務器先生成 json 數據,而後以 javascript 語法的方式,生成一個function , function 名字就是傳遞上來的參數 jsonp,最後將 json 數據直接以入參的方式,放置到 function 中,這樣就生成了一段 js 語法的文檔,返回給客戶端。
3. 客戶端瀏覽器,解析script標籤,並執行返回的 javascript 文檔,此時數據做爲參數,傳入到了客戶端預先定義好的 callback 函數裏.(動態執行回調函數)
舉個例子,假如須要從服務器(http://www.a.com/user?id=123)獲取的數據以下:安全
{"id": 123, "name" : 張三, "age": 17}
那麼,使用JSONP方式請求(http://www.a.com/user?id=123?callback=foo)的數據將會是以下: 服務器
foo({"id": 123, "name" : 張三, "age": 17});
固然,若是服務端考慮得更加充分,返回的數據可能以下: 網絡
try{foo({"id": 123, "name" : 張三, "age": 17});}catch(e){}
這時候咱們只要定義一個foo()函數,並動態地建立一個script標籤,使其的src屬性爲http://www.a.com/user?id=123?callback=foo: app
function executeJsonp(url){ var eleScript= document.createElement("script"); eleScript.type = "text/javascript"; eleScript.src = url; document.getElementsByTagName("head")[0].appendChild(eleScript); } function foo(data){ for(var p in data){ console.log(data[p]); } } var url = "http://www.a.com/user?id=123?callback=foo"; executeJsonp(url)
第一種方法是在ajax函數中設置dataType爲'jsonp':
$.ajax({ dataType: 'jsonp', url: 'http://www.a.com/user?id=123', success: function(data){ //處理data數據 } });
getJsonp: function(url, param, callback) { $.ajax({ url: url, data: param, dataType: "jsonp", success: callback, error: function(data){ alert('網絡異常,請稍後再試!'); } }) }
第二種方法是利用getJSON來實現,只要在地址中加上callback=?參數便可:
$.getJSON('http://www.a.com/user?id=123&callback=?', function(data){ //處理data數據 });
也能夠簡單地使用getScript方法:
/此時也能夠在函數外定義foo方法 function foo(data){ //處理data數據 } $.getJSON('http://www.a.com/user?id=123&callback=foo');
JSONP的優勢是:它不像XMLHttpRequest對象實現的Ajax請求那樣受到同源策略的限制;它的兼容性更好,在更加古老的瀏覽器中均可以運行,不須要XMLHttpRequest或ActiveX的支持;而且在請求完畢後能夠經過調用callback的方式回傳結果。
JSONP的缺點則是:它只支持GET請求而不支持POST等其它類型的HTTP請求;它只支持跨域HTTP請求這種狀況,不能解決不一樣域的兩個頁面之間如何進行JavaScript調用的問題。