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(这部分会在后文浏览器支持部分介绍)。