出于对网站安全性的要求,两个不同域名的网站之间是不能通过前端技术互相发送请求的。但有时我们又需要使用这样的机制。比如:网站需要制作一个天气预报插件,或者需要开发两个网站,一个供外部用户使用,一个供内部用户使用,而外部使用的网站需要调用内部网站等情况下,就需要使用跨域调用的技术。此类技术的一个代表就是Jsonp。
Jsonp(JSON with Padding)是资料格式 json 的一种“使用模式”,可以让网页从别的网域获取资料。Jsonp有很好的浏览器兼容性,包括IE6在内的大多浏览器都支持这种标准跨域数据访问方式。它的核心原理是利用script标签的跨域特性,间接实现数据调用。很容易理解了,利用script标签的话只能发送GET请求,无法发送POST请求。为便于理解,我先用原生Javascript的一个例子来说明。
例1:
A域名(a.com)下的index.html:function jsonpcallback(json){ //Jsonp回调函数,参数为返回的json数据
//对数据的后续操作。。。
console.log(json);
}
创建script标签 src="http://b.com/api.php?uid=5344&callback=jsonpcallback",发送请求
B域名(b.com)下的api.phpif(isset($_GET['uid']) && $_GET['uid']>0){
$uid = intval($_GET['uid']);
}
if(isset($_GET['callback'] && $_GET['callback']!=''){
$callback = $_GET['callback'];
}
//从数据库中调uid为5344的用户的数据...
$data = array('uid' => 5344,'name' => 'hxz','age' => 28,'sex' => '男');
$json = json_encode($data);
echo $callback."($json)";
运行 http://a.com/index.html 即可在开发者工具的console中看到成功调到的个人信息数据。
其具体流程如下:1.先定义一个标准JS函数,参数为一个json对象。
2.再写一个script标签请求api.php这个页面。把要调用的函数名和其他一些信息用url参数发送。
3.编写api.php,处理get请求并返回一个JS函数调用。这样A域名下的页面中的第二个script标签中的内容是jsonpcallback({uid:5344,...});,也就相当于调用了流程1中所述的标准JS函数。
4.已经成功取得了数据,只需在jsonpcallback函数中进行后续数据处理。
如果已经完全理解上述例子的话相信大家已经能够理解Jsonp的原理了,那么接下来介绍jsonp在使用上的优化。
可以发现a.com/index.html中定义了两个script标签,如此写法太过繁琐。故而一般JS框架都对jsonp有一定的封装以达到易于使用的目的。下面就以Jquery框架来优化index.html中的代码书写:
例2:$.ajax({
url: http://b.com/api.php,
data:{uid:5344},
dataType: 'jsonp',
jsonp:'callback',
//在一个 jsonp 请求中重写回调函数的名字。这个值用来替代在 "callback=?" 这种 GET 请求中 URL 参数里的 "callback" 部分,比如 {jsonp:'onJsonPLoad'} 会导致将 "onJsonPLoad=?" 传给服务器。
jsonpCallback: 'jsonpcallback',
//这主要用来让 jQuery 生成度独特的函数名,这个值用来替代在 "callback=?" 这种 GET 请求中 URL 参数里的 "?" 部分
success:function(json){
//对数据的后续操作。。。
console.log(json);
}
});
b.com/api.php中代码不变。这样JQuery就会自动动态加上例1中的script请求标签发送请求了。
显然Jquery对jsonp的封装并没有减少多少代码量。但写过一般ajax请求的同学可以发现,这个写法是为把ajax和jsonp的写法统一起来,使jsonp看上去就和一般的ajax请求没什么本质上区别。但其实jsonp和ajax是完全不同的实现原理,ajax是使用XHR(XmlHttpRequest)的新兴技术,而jsonp仅仅使用了script标签的特性,这是一个连很古老的浏览器都支持的技术。所以我不推荐使用jquery封装的代码来理解jsonp,它容易误导初学者。故而本文从一开始就使用了原生Js代码来讲解原理。请大家在理解原理的基础上再使用JS框架封装的代码来书写。如此才能完全掌握jsonp技术。
Jsonp的GET请求介绍完了,那它能发送POST请求吗?,这个问题将在下篇中进行介绍,敬请期待!