JSONP是如何实现跨域请求的?
27 March 2014
学习自:说说JSON和JSONP,也许你会豁然开朗,含jQuery用例
条件
- 由于JS的同源策略限制,无法通过AJAX向其他域发送请求;
- 凡是拥有”src”这个属性的标签都拥有跨域的能力,比如
<script>
、<img>
、<iframe>
; - JS可动态为当前DOM结构增加和删除节点;
- 当浏览器请求一个JS文件时,会执行请求返回的内容。
实现方法
基于上述4个条件,我们可以这样做:
- 在HTML页面中加入:
<script type="text/javascript" src="http://localhost/jsonp.php"></script>
; - 后台
jsonp.php
页面:echo 'alert("Hi, men.")';
。
载入HTML页面就会看到提示框。
如果服务端输出一个函数调用(该函数为JS客户端所期望的函数),参数为服务端处理好的JSON数据,那么不就能够很好地实现跨域请求了么?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Test</title>
<!--<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.1.min.js"></script>-->
<script type="text/javascript">
var sayHi = function (data) {
alert('Hi, ' + data.name);
}
var jsonpUrl = 'Http://localhost/jsonp.php?callback=sayHi';
var script = document.createElement('script');
script.setAttribute('src', jsonpUrl);
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</head>
<body>
</body>
</html>
1
2
3
4
5
<?php
if (isset($_GET['callback'])) {
echo $_GET['callback'].'('.json_encode(['name'=>'rokety']).')';
}
?>
JQuery使用Ajax发送JSONP请求
其实JQuery是将上面讲到的实现方法包装进了Ajax中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Test</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript">
function sayHi (data) {
alert('Hi, ' + data.name + '. Your profile: ' + data.description);
}
jQuery(document).ready(function(){
$.ajax({
type : "GET",
url : "http://localhost/jsonp.php",
dataType : "jsonp",
data : "name=rokety",
jsonp : "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(默认为:callback)
jsonpCallback:"sayHi",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名
err : function () {
alert('Request Fail!');
}
});
});
</script>
</head>
<body>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
$user = [
'rokety' => 'A programmer!'
];
if (isset($_GET['callback']) && isset($_GET['name'])) {
if (isset($user[$_GET['name']])) {
echo $_GET['callback'].'('.json_encode(
[
'name'=>$_GET['name'],
'description'=>$user[$_GET['name']]
]
).')';
} else {
echo $_GET['callback'].'('.json_encode(
[
'name'=>$_GET['name'],
'description'=>'unknow person!'
]
).')';
}
}
?>
注意
JSONP并不支持POST请求,根据实现原理也应该能看出这一点。