通过JSONP实现跨域
2010-06-26
JSONP即JSON with Padding。由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源。如果要进行跨域请求,我们可以通过使用 html的script标记来进行跨域请求,并在响应中返回要执行的script代码,其中可以直接使用JSON传递javascript对象。这种跨域 的通讯方式称为JSONP。
对于上面的解释,我们可以简单这样理解:JSONP就是可以通过JavaScript文件进行跨域通讯的方式,例如:现在各大网站风靡的搜索提示。注意:JSONP服务器端代码需要充分做好安全措施。
下面是一个简单的JSONP:
01 |
var JSONP = document_createElement_x( "script" ) ; |
02 |
//FF:onload IE:onreadystatechange |
03 |
JSONP.onload = JSONP.onreadystatechange = function (){ |
04 |
//onreadystatechange,仅IE |
05 |
if (! this .readyState || this .readyState === "loaded" || this .readyState === "complete" ) { |
06 |
alert($( "#demo" ).html()); |
07 |
JSONP.onload = JSONP.onreadystatechange = null //请内存,防止IE memory leaks |
08 |
} |
09 |
} |
10 |
JSONP.type = "text/javascript" ; |
11 |
JSONP.src = "http://www.nowamagic.net/js/jquery.js" ; |
13 |
document.getElementsByTagName_r( "head" )[0].a(JSONP); |
简单解释:我们通过创建script,然后指定它的src等属性,然后插入到head执行。
建议:onload、onreadystatechange 写在src赋值之前,防止载入js太快而没有给onload、onreadystatechange 赋值(Image对象在IE下具有此类现象)。
我们可以首先定义一个函数来执行JSONP返回的数据,然后通过JSONP的src传此函数给后台,进行处理,返回可执行的函数。例如下面代码:
1 |
function jsonpHandle(a){ |
2 |
alert(a); |
3 |
} |
4 |
var JSONP = document_createElement_x( "script" ) ; |
5 |
JSONP.type = "text/javascript" ; |
6 |
JSONP.src = "http://www.js8.in/jsonp.php?callback=jsonpHandle" ; |
8 |
document.getElementsByTagName_r( "head" )[0].a(JSONP); |
1 |
echo $_GET [ "callback" ]. "('hello,world')" ; |
普通的ajax请求只能进行同域的数据交互,但是一旦有跨域的情况就不行了。但是jsonp不同,他可以利用浏览器标签达到跨域的目的。 其实 jsonp 是个很简单的一个东西。主要是利用了 <script> 标签对 javascript 文档的动态解析。
Script 标签本身的功能就是异步加载js并且会以js的方式解析执行。一旦在script的标签里加入src的属性,浏览器执行到这个标签时就回去请求指定的地 址,如果服务器返回的是js格式的代码,甚至可以是js的函数,只要是能被js解析的,都可以被执行,这也就是jsonp的原理。
简单使用jsonp的demo:
01 |
<!DOCTYPE HTML> |
02 |
< html > |
03 |
< head > |
04 |
< Meta charset = "gbk" /> |
05 |
< title ></ title > |
06 |
</ head > |
07 |
< body > |
08 |
< div id = "content" > |
09 |
|
10 |
</ div > |
11 |
12 |
</ body > |
13 |
< script type = "text/javascript" > |
14 |
var load = function(message){ |
15 |
document.getElementByIdx_x("content").innerHTML=message; |
16 |
} |
17 |
</ script > |
18 |
< script type = "text/javascript" src = "jsonpContent.html?callback=load" ></ script > |
19 |
</ html |
这是最基本的jsonp的原理。
以http://www.nowamagic.net/test.PHP这个链接为例,在url后面带上参数callback=AjaxListLoader.reload
01 |
<!DOCTYPE HTML> |
02 |
<html> |
03 |
<head> |
04 |
<Meta charset= "gbk" /> |
05 |
<title></title> |
06 |
<script type= "text/javascript" |
07 |
src= "http://ajax.googleapis.com/ajax/libs/yui/2.8.1/build/yuiloader-dom-event/yuiloader-dom-event.js" ></script> |
08 |
</head> |
09 |
<body> |
10 |
<div id= "console" ></div> |
11 |
<script> |
12 |
var url = "http://www.nowamagic.net/test.php" ; |
13 |
14 |
var AjaxLoader = function () { |
15 |
var loader = function () { |
16 |
YAHOO.util.Get.script(url + '?callback=AjaxLoader.reload' ,{ |
17 |
onSuccess: function () { |
18 |
}, |
19 |
onFailure: function () { |
20 |
YAHOO.util.Dom.get( "console" ).innerHTML = '请求失败' ; |
21 |
}, |
22 |
timeout: 10000, |
23 |
autopurge: true , |
24 |
charset: 'GBK' |
25 |
}); |
26 |
}; |
27 |
28 |
return { |
29 |
init: function () { |
30 |
loader(); |
31 |
YAHOO.util.Dom.get( "console" ).innerHTML = '开始请求' ; |
32 |
33 |
}, |
34 |
|
35 |
reload: function () { |
36 |
YAHOO.util.Dom.get( "console" ).innerHTML = '请求成功,调用成功' ; |
37 |
} |
38 |
}; |
39 |
}(); |
40 |
41 |
AjaxLoader.init(); |
42 |
43 |
44 |
</script> |
45 |
</body> |
46 |
47 |
</html |