我们知道,普通的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();
-
- script.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脚本就行了