JSONP实现Ajax跨域请求

前言

由于浏览器存在同源策略的机制,所谓同源策略就是阻止从一个源(域名,包括同一个根域名下的不同二级域名)加载的文档或者脚本获取/或者设置另一个源加载的文档属性.

但比较特别的是:由于同源策略是浏览器的限制,所以请求的响应和发送是可以进行的,只不过浏览器不支持罢了.

同源策略限制

浏览器的同源策略并不是对所有的请求都有限制的:

  • 限制:XmlHttpRequest
  • 不限制:img iframe script等等具有src属性的标签

利用src属性标签实现跨域请求

基本思路

利用script标签,src导入目标域名的接口,在文档数的head标签中添加一行script标签,得到内容后将scprit标签删除,返回的解析后的参数即为得到的数据.

利用script标签实现跨域代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>Index</h1>

    <input type="button" onclick="Ajax();" value="普通AJax"/>
    <input type="button" onclick="Ajax2();" value="跨域普通AJax"/>
    <input type="button" onclick="Ajax3();" value="跨域牛逼AJax"/>
    <input type="button" onclick="Ajax4();" value="江西TV"/>

    <script src="/static/jquery-2.1.4.min.js"></script>
    <script>
    		// 原生ajax,测试无效
        function Ajax(){
            $.ajax({
                url: '/get_data/',
                type: 'POST',
                data: {'k1': 'v1'},
                success: function (arg) {
                    alert(arg);
                }
            })
        }
			// 使用ajax跨域请求,测试无效
        function Ajax2(){
            $.ajax({
                url: 'http://wupeiqi.com:8001/api/',
                type: 'GET',
                data: {'k1': 'v1'},
                success: function (arg) {
                    alert(arg);
                }
            })
        }
        
        // 利用script标签,得到数据
        function Ajax3(){
            // script
            // alert(api)
            var tag = document.createElement('script');
            tag.src = 'http://wupeiqi.com:8001/api/';
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }
        function fafafa(arg){
            console.log(arg);
        }
        
        // 例子,获取江西卫视的节目单
        function Ajax4(){
            // script
            // alert(api)
            var tag = document.createElement('script');
            tag.src = 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403';
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }
        function list(arg){
            console.log(arg);
        }
    </script>
</body>
</html>

JSONP实现ajax跨域

以上的代码其实也是jsonp的基本思路

基本的jsonp写法

$.ajax({
	url:..
	type: 'GET',
	dataType: 'jsonp',
	//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
	jsonp: 'callback',
	//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
	jsonpCallback: 'list'
})
	
function list(arg){
	
}

解释:

jsonp: callback      #发送给请求处理程序的,被请求端通过request.GET.get("callback"),获得jsonp回调函数的参数

jsonpCallback: 'list' #定义回调函数的名称,然后后面通过list(...)来处理获取数据

生产示例

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="button" onclick="Jsonp1();"  value='提交'/>
    </p>

    <p>
        <input type="button" onclick="Jsonp2();" value='提交'/>
    </p>

    <script type="text/javascript" src="jquery-1.12.4.js"></script>
    <script>
        function Jsonp1(){
            var tag = document.createElement('script');
            tag.src = "http://c2.com:8000/test/";
            document.head.appendChild(tag);
            document.head.removeChild(tag);

        }

        function Jsonp2(){
            $.ajax({
                url: "http://c2.com:8000/test/",
                type: 'GET',
                dataType: 'JSONP',
                success: function(data, statusText, xmlHttpRequest){
                    console.log(data);
                }
            })
        }


    </script>
</body>
</html>

###基于JSONP实现跨域Ajax - Demo

JSONP不能发送POST请求

究其根源,通过script标签的src属性进行跨域请求,<script src='http://www.jxntv.cn/data/jmd-jxtv2.html?callback=qwerqweqwe&_=1454376870403'>最后全部都会转换成GET请求,哪怕是你把type改为POST.

别处copy的例子,供参考

<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>

其他ajax跨站请求方式

需要顺带提一句的是,跨站请求还有另一种方式:cors,跨站资源共享,但此中方式对浏览器版本有要求,IE8以下的均不支持.

CORS与JSONP相比,无疑更为先进、方便和可靠。

    1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。

    2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。

    3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS(这部分会在后文浏览器支持部分介绍)。
posted @ 2016-10-17 14:42  ccorz  阅读(3512)  评论(0编辑  收藏  举报