(Ajax) 淺談 JSONP 的原理與實現

1、什麼是JSONP

1.1 同源策略

若是兩個頁面擁有相同的協議端口(若是指定),和主機,那麼這兩個頁面就屬於同一個
同源策略分爲:javascript

  • DOM同源策略:禁止對不一樣源頁面DOM進行操做html

  • XMLHttpRequest同源策略:禁止向不一樣源的地址發起HTTP請求
    因而可知,Ajax禁止跨域。java

1.2 JSONP的原理

JSONPJSON with Padding的簡稱,通常用來解決Ajax跨域的問題。它是這樣產生的:jquery

  1. 頁面上調用js文件時不受跨域的影響,並且,凡是擁有src屬性的標籤都擁有跨域的能力,好比<script><img><iframe>ajax

  2. 能夠在遠程服務器上設法把數據裝進js格式的文件裏,供客戶端調用處理,實現跨域。json

  3. 目前最經常使用的數據交換方式是JSON,客戶端經過調用遠程服務器上動態生成的js格式文件(通常以JSON後綴)。跨域

  4. 客戶端成功調用JSON文件後,對其進行處理。瀏覽器

  5. 爲了便於客戶端使用數據,逐漸造成了一種非正式傳輸協議,人們把它稱做JSONP,該協議的一個要點就是容許用戶傳遞一個callback參數給服務端,而後服務端返回數據時會將這個callback參數做爲函數名來包裹住JSON數據,這樣客戶端就能夠隨意定製本身的函數來自動處理返回數據了。安全

2、JSONP的客戶端具體實現

2.1 上文已指出,頁面可執行跨域的js代碼(符合安全策略的),那麼:服務器

<script type="text/javascript">
  var localHandler = function (data) {
    alert('跨域的remote.js文件能夠調用本函數,帶來的數據是:' + data.result);
  };
</script>
<script type="text/javascript" src = "http://remoteserver.com/remote.js"></script>

remote.js的代碼:

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

運行後,成功彈出提示窗口,跨域成功。但問題是,如何讓遠程js知道它應該調用的本地函數叫什麼名字?

2.2 只要服務端提供的js腳本是動態生成的就好了,調用者能夠傳一個參數過去告訴服務端本地函數的名字,因而服務端就能夠按照客戶的需求來生成js腳本並相應了。

var flightHandler = function (data) {
    alert('你查詢的航班結果是:票價 ' + data.price + '元,餘票' + data.tickets + '張。');
  };
  var url = 'http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler';
  var script = document.createElement('script');
  script.setAttribute('src', url);
  document.getElementsByTagName('head')[0].appendChild(script);

並無直接把遠程js寫死,而是編碼事項動態查詢。這是JSONP的核心部分。在調用的url中傳遞了一個code參數,告訴服務器要查的是CA1998次航班的信息,而callback參數告訴服務器,本地調用的函數叫作flightHandler
服務器的flightResult.aspx生成了如下代碼提供給頁面:

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

運行一下頁面,成功提示窗口,JSONP的執行全過程順利完成。

2.3 jQuery代碼

$(function() {
  $('button').on('click', function(event) {
    event.preventDefault();
    $.ajax({
      type: 'GET',
      async: false,
      url: 'http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998',
      dataType: 'jsonp',
      jsonp: 'callback',
      jsonpCallback: 'flightHandler',  // 默認爲jQuery自動生成的隨機函數名
      success: function (json) {
        alert('你查詢的航班結果是:票價 ' + json.price + '元,餘票' + json.tickets + '張。');
      },
      error: function () {
        alert('fail');
      }
    });
  });
});

jQuery自動生成回調函數並把數據取出來供success屬性方法來調用。

3、JSONPAjax的關係

  • AjaxJSONP這兩種技術看起來很像,目的也同樣,都是請求一個url,而後把服務器返回的數據進行處理,所以jQuery等框架都把JSONP做爲Ajax的一種形式。

  • 實際上AjaxJSONP有着本質上的不一樣。Ajax的核心是經過XMLHttpRequest獲取數據,而JSONP的核心則是動態添加<script>標籤來調用服務器提供的js文件。

  • AjaxJSONP的區別也不在因而否跨域,Ajax經過服務端代理也能夠跨域,JSONP也可獲取同源數據。

4、參考

  1. 【原創】說說JSON和JSONP,也許你會豁然開朗,含jQuery用例

  2. 深刻淺出JSONP--解決ajax跨域問題

  3. 瀏覽器的同源策略 - MDN

相關文章
相關標籤/搜索