剑客
关注科技互联网

(Ajax) 浅谈 JSONP 的原理与实现

一、什么是 JSONP

1.1 同源策略

如果两个页面拥有相同的 协议
端口
(如果指定),和 主机
,那么这两个页面就属于同一个

同源策略分为:

  • DOM
    同源策略:禁止对不同源页面 DOM
    进行操作

  • XMLHttpRequest
    同源策略:禁止向不同源的地址发起 HTTP
    请求

    由此可见, Ajax
    禁止跨域。

1.2 JSONP
的原理

JSONP
JSON with Padding
的简称,一般用来解决 Ajax
跨域的问题。它是这样产生的:

  1. 页面上调用 js
    文件时不受跨域的影响,而且,凡是拥有 src
    属性的标签都拥有跨域的能力,比如 <script>
    <img>
    <iframe>

  2. 可以在远程服务器上设法把数据装进 js
    格式的文件里,供客户端调用处理,实现跨域。

  3. 目前最常用的数据交换方式是 JSON
    ,客户端通过调用远程服务器上动态生成的 js
    格式文件(一般以 JSON
    后缀)。

  4. 客户端成功调用 JSON
    文件后,对其进行处理。

  5. 为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作 JSONP
    ,该协议的一个要点就是允许用户传递一个 callback
    参数给服务端,然后服务端返回数据时会将这个 callback
    参数作为函数名来包裹住 JSON
    数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

二、 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
属性方法来调用。

三、 JSONP
Ajax
的关系

  • Ajax
    JSONP
    这两种技术看起来很像,目的也一样,都是请求一个 url
    ,然后把服务器返回的数据进行处理,因此 jQuery
    等框架都把 JSONP
    作为 Ajax
    的一种形式。

  • 实际上 Ajax
    JSONP
    有着本质上的不同。 Ajax
    的核心是通过 XMLHttpRequest
    获取数据,而 JSONP
    的核心则是动态添加 <script>
    标签来调用服务器提供的 js
    文件。

  • Ajax
    JSONP
    的区别也不在于是否跨域, Ajax
    通过服务端代理也可以跨域, JSONP
    也可获取同源数据。

四、参考

  1. 【原创】说说JSON和JSONP,也许你会豁然开朗,含jQuery用例

  2. 深入浅出JSONP–解决ajax跨域问题

  3. 浏览器的同源策略 – MDN

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址