jsonp
我们知道,普通的ajax请求存在跨域无权限访问的问题,这是浏览器的安全策略在起作用
index.php:
<?php $info = '{"code" : 10,"title" : "jsonp","name" : "rgy"}';echo $info;
?>
test.html中的js代码:
$.ajax({type: "post",url: "http://localhost/jsonptest/index.php",dataType: "json",success: function(data) {console.log(data);},error: function(data) {console.log("fail");}});
举个例子,首先test.html与index.php不在同一域中,test.html当访问index.php时:,通常会出现如下图所示的情况:
怎样解决这个问题呢?
这里有两种思路:
第一种是修改服务端代码,为index.php加上header(Access-Control-Allow_Origin:*);允许所有来源的请求访问该资源。
第二种思路就是通过jsonp的方式
下面先介绍第一种方法:
将index.php修改成如下形式:
<?php header('Access-Control-Allow-Origin:*'); ?><?php $info = '{"code" : 10,"title" : "jsonp","name" : "rgy"}';echo $info;
?>
再通过test.html进行跨域访问就没有问题了,结果如下:
第二种方法:
首先将服务端代码改成如下形式:
<?php$callback = $_GET['callback']; $info = '{"code":10,"title":"jsonp","name":"rgy"}';echo $callback."(".$info.")";?>
test.html可以通过如下方式进行访问:
$.ajax({type: "get",url: "http://todolist6.sinaapp.com/pages/QuickWayGetInfo.php",dataType: "jsonp",jsonp: "callback",success: function(data) {console.log(data);},error: function() {console.log("fail");}
<span style="white-space:pre"> </span>});
$.getJSON("http://todolist6.sinaapp.com/pages/QuickWayGetInfo.php?callback=?",function(data){console.log(data);});
结果如下:
这是用的jquery帮我们封装好的方法,虽然使用起来方便,但是却不利于大家理解jsonp的原理,下面就是原生的js模拟一下jsonp的访问过程
说白了,就是利用src属性能够跨域访问的特性
var showInfo = function(data){console.log(data);
}var url = "http://todolist6.sinaapp.com/pages/QuickWayGetInfo.php?callback=showInfo";var script = document.createElement('script');
script.setAttribute('src', url);
document.getElementsByTagName('head')[0].appendChild(script);
先定义了一个回调方法showInfo,然后将其当作url参数的一部分发送到服务端,服务端通过字符串拼接的方式将数据包裹在回调方法中,再返回回来然而这样使用起来相当不方便,在不使用其他js库的情况下,对这个过程进行封装:
function loadScript(xyUrl, callback){var head = document.getElementsByTagName('head')[0];var script = document.createElement('script');script.type = 'text/javascript';script.src = xyUrl;script.onload = script.onreadystatechange = function(){if((!this.readyState || this.readyState === "loaded" || this.readyState === "complete")){callback && callback();// Handle memory leak in IEscript.onload = script.onreadystatechange = null;//人工回收内存if ( head && script.parentNode ) {head.removeChild( script );}}};head.insertBefore( script, head.firstChild );
}//var url = "http://todolist6.sinaapp.com/pages/QuickWayGetInfo.php?callback=showInfo";loadScript(url, showInfo);var showInfo = function(data){console.log(data.name);
}
总结:
jsonp就是利用<script>标签中src属性能够跨域访问的特性,先定义了一个回调方法,然后将其当作url参数的一部分发送到服务端,服务端通过字符串拼接的方式将数据包裹在回调方法中,再返回回来
ajax和jsonp其实本质上是不同的东西,虽然jquery将其整合在了一块儿,ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本
jsonp是一种非强制性协议,或者说它更像是一种方法,如同ajax一样,它也不一定非要用json格式来传递数据,只要返回是内容是可执行的js脚本就行了