3.9 跨域的AJAX-JSONP

默认情况下,浏览器不允许AJAX进行跨域访问,这主要是出于安全方面的考虑。事实上,开发人员存在很多跨域访问服务器的需求,该怎么办呢?JSONP技术就是其中一种常见的AJAX跨域访问的解决方案。

JSONP(JSON with Padding)是资料格式JSON(JavaScript Object Notation)的一种“使用模式”,可以让网页从别的网域获取资料。JSONP是一个非官方协议,允许服务器端与客户端之间实现跨域访问。JSONP也是一种典型的面向数据结构的分析和设计方法,以活动为中心,一连串活动的顺序组合成一个完整的工作进程。

之所以会有跨域这个问题,根本原因是浏览器的同源策略限制。简单理解同源策略,指的是阻止代码获得或者更改从另一个域名下获得的文件或信息。解决这个限制的一个相对简单的办法是让服务器端作为中介发送请求,或者使用框架(Frames)的形式引入脚本文件。但是,这些解决方案都不够灵活。

有一个很巧妙的办法是在页面中使用动态代码元素,这些动态代码的源指向目标服务地址,并在自己的代码中加载数据。当这些代码加载执行时,同源策略就不会限制。一般来说,这些数据的加载格式是JSON。

通过使自定义函数加载动态JSON数据从而处理动态数据,这项技术叫做Dynamic JavaScript Insertion。

【示例3-11】jq_dyjs.html

        01    <html>
        02         <head>
        03             <title>动态JavaScript调用</title>
        04               <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        05               <script type="text/javascript">
        06                 function showAge(data){                   //自定义函数
        07                          alert("Name:" + data.name + ", Age:" + data.age);
                                                                  //展示信息数据
        08                    }
        09                 var url = "jquery/info.js";               //外部的URL地址
        10                    var script = document.createElement('script');
                                                                  //动态创建脚本标签
        11                 script.setAttribute('src', url);        //设置脚本的路径
        12                 //加载脚本
        13
         document.getElementsByTagName('head')[0].appendChild(script);
        14               </script>
        15         </head>
        16         <body style="text-align:center">
        17         </body>
        18    </html>

动态JavaScript调用外部URL脚本的代码如下:

        //info.js中的代码
        var data = {name:'Mike', age:20};                 //定义一条数据
        showAge(data);                               //回调函数

本示例的效果如图3.12所示。

图3.12 动态JavaScript调用

在本网页里,定义一个需要的函数,然后只需要把外部URL的脚本写上数据已经动态回调,就可以实现跨域的访问了,这也被称为动态代码调用。JSONP的根本原理也是这样,只不过它处理得更优雅一些,而且从jQery1.2以后开始支持JSONP的调用。