为了保证用户的安全,浏览器会防止网页中发起跨域请求,但我们又会有这样的需求,jsonp是一个非官方的跨域办法,jquery中有实现。
$.getJSON()
当请求的URL中有callback=?
时会是一个跨域请求,请求的callback函数会由jquery根据时间随机生成。$.getScript()
也一样,只不过预期返>回是一个js文件。
不管怎么样$.getJSON()
和$.getScript()
最终低层都是使用的$.ajax()
。一个跨域请求举例:
$.ajax({
url: 'http://example.com/data.json?callback=?',
dataType: 'jsonp',
type: 'GET',
timout: 5000,
jsonpCallback: 'handle_data',
crossDomain: true,
success: function(data) {
console.log("获取数据成功");
do_something(data);
},
error: function(x, t, m) {
if(t == "timeout") {
alert("获取失败");
}
}
});
callback=?
中的问题是个占位符,当有jsonpCallback时,会被替换成jsonpCallback的值或者是返回值(如果jsonpCallback是函数), 否则就是随机生成,当不需要缓存的情况下,随机生成能更安全。crossDomain为true表示强制跨域,哪怕同一个域名下,也会发起跨域请求。
跟普通ajax请求一样,success函数还是处理一个json数据。当然服务端返回的结果不会是json了,而是一个函数包住的json,更确切地说实际是一条javascript代码, 比如:handle_data({'name':'test', 'age':123})
实际上跨域请求jsonp不是ajax请求,浏览器因为安全考虑也不允许js代码这么做,所以jquery实际是在页面中插入了一个<script>
节点, 请求完成后删除节点,但返回的结果,即js代码,会占用浏览器内存。这也就是为什么jsonp只能是GET请求,而且不允许设置为同步请求。又由于解析及处理<script>
节点是浏览器行为, 成功有结果代码的执行,而失败却无法处理,比如404错误,所以只能以定时查询的方式来处理错误,设置一个足够长的timeout值,error函数中通过判断超时来估计请求失败了。