Jsonp的简单例子

JSONP 是JSON with padding(填充式JSON 或参数式JSON)的简写,是应用JSON 的一种新方法,在后来的Web 服务中非常流行。JSONP 看起来与JSON 差不多,只不过是被包含在函数调用中的JSON,就像下面这样。

1
callback({ "name": "Nicholas" });

JSONP 由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的JSON数据。下面是一个典型的JSONP请求。

1
http://freegeoip.net/json/?callback=handleResponse

这个 URL 是在请求一个JSONP 地理定位服务。通过查询字符串来指定JSONP 服务的回调参数是很常见的,就像上面的URL 所示,这里指定的回调函数的名字叫handleResponse()。

JSONP 是通过动态<script>元素来使用的,使用时可以为src 属性指定一个跨域URL。这里的<script>元素与<img>元素类似,都有能力不受限制地从其他域加载资源。因为JSONP 是有效的JavaScript 代码,所以在请求完成后,即在JSONP响应加载到页面中以后,就会立即执行。来看一个例子。

1
2
3
4
5
6
7
function handleResponse(response){
alert("You’re at IP address " + response.ip + ", which is in " +
response.city + ", " + response.region_name);
}
var script = document.createElement("script");
script.src = "http://freegeoip.net/json/?callback=handleResponse";
document.body.insertBefore(script, document.body.firstChild);

这个例子通过查询地理定位服务来显示你的IP 地址和位置信息。

JSONP 之所以在开发人员中极为流行,主要原因是它非常简单易用。与图像Ping相比,它的优点在于能够直接访问响应文本,支持在浏览器与服务器之间双向通信。不过,JSONP 也有两点不足。

首先,JSONP 是从其他域中加载代码执行。如果其他域不安全,很可能会在响应中夹带一些恶意代码,而此时除了完全放弃JSONP 调用之外,没有办法追究。因此在使用不是你自己运维的Web 服务时,一定得保证它安全可靠。

其次,要确定JSONP 请求是否失败并不容易。虽然HTML5 给<script>元素新增了一个onerror事件处理程序,但目前还没有得到任何浏览器支持。为此,开发人员不得不使用计时器检测指定时间内是否接收到了响应。但就算这样也不能尽如人意,毕竟不是每个用户上网的速度和带宽都一样。

jsonp.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
25
26
27
28
29
30
31
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript">
window.onload = function() {
var btn1 = document.getElementById('btn1');
btn1.onclick = function() {
$.ajax({
url: 'http://api.money.126.net/data/feed/0000001,1399001?callback=refreshPrice',
type: 'get',
dataType: 'jsonp',
jsonpCallback:'refreshPrice',
success: function(data) {
var info = document.getElementById('test-jsonp');
info.innerHTML = '当前价格:' + data['0000001'].name + ':' + data['0000001'].price + data['1399001'].name + ':' + data['1399001'].price
}
})
}
}


</script>
</head>
<body>
<p id="test-jsonp">当前价格:</p>
<button id="btn1">刷新</button>
</body>
</html>