JSONP和JSON是不一样的 。JSON(JAVAScript Object Notation)是一种基于文本的数据交换方式,或者叫做数据描述格式 。而JSONP(JSON with Padding)是一种方式或者说非强制性协议 。它是为了解决某个难题而产生的一种技术方式 。
为什么会用到JSONP呢?
我们平时在用ajax请求服务端数据时,一般是这么写的:
Copy$.ajax({ type: "get", url: "getData.php", dataType: "json", success: function (data, textStatus, jqXHR) { console.log(data); }, error: function (XMLHttpRequest, textStatus, errorThrown) { alert('fail'); }});这是一段很普通的基于jQuery的AJAX请求,不会有什么问题 。注意到:url里是getData.php,说明这个文件url是基于当前服务器的,例如可能是localhost,也就是前端发出的请求来源是localhost,后端肯定也是localhost 。他们俩是在同一个域名下 。当然,平时我们也不会特别注意 。
这时候,假如这个url变成其它服务器上的地址,例如:'http://apis.juhe.cn/mobile/get?phone=13429667914&key=',我们再把请求发送出去,会发现出问题了 。大家可以手动写个示例看看 。
DEMO: 为什么使用jsonp?
出什么问题了?被限制请求了!
CopyXMLHttpRequest cannot load http://apis.juhe.cn/mobile/get?phone=13429667914&key=. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://demo.52fhy.com' is therefore not allowed access.也就是请求来源与服务器不是同一个域名,不允许访问 。这就是浏览器同源策略:
Copy所谓"同源"指的是"三个相同":协议相同域名相同端口相同举例来说,http://www.example.com/dir/page.html这个网址,协议是http://,域名是www.example.com,端口是80(默认端口可以省略) 。它的同源情况如下 。http://www.example.com/dir2/other.html:同源http://example.com/dir/other.html:不同源(域名不同)http://v2.www.example.com/dir/other.html:不同源(域名不同)http://www.example.com:81/dir/other.html:不同源(端口不同)同源政策规定,AJAX请求只能发给同源的网址,否则就报错 。
那么,这时候该怎么办呢?我就是想通过js请求对方服务器上的资源!
除了架设服务器代理(浏览器请求同源服务器,再由后者请求外部服务),有三种方法规避这个限制 。
- JSONP
- WebSocket
- CORS
如何使用JSONP首先前端这边代码得改改,假设先不用jQuery:
Copy<script type="text/JavaScript">//跨域发送HTTP请求,从服务端获取数据,callback指定回调函数名称var url = 'http://demo.52fhy.com/jsonp/handJsonp.php?callback=handler';function getHello() { var script = document.createElement('script'); script.setAttribute('src', url); document.querySelector("head").AppendChild(script);}// 处理函数function handler(data) { console.log(data); // our code here...}</script><input type="button" value=https://www.isolves.com/it/cxkf/bk/2019-08-30/"发送跨域HTTP请求,获取数据" onclick="getHello()" />后端服务器也要改改 。
例如,在PHP语言中,后端服务器在API里返回JSON数据,一般是这么写的:
Copy$data = https://www.isolves.com/it/cxkf/bk/2019-08-30/array('name' => '52fhy', 'age' => '22');echo json_encode($data);exit;这里需要改成:
Copy$data = https://www.isolves.com/it/cxkf/bk/2019-08-30/array('name' => '52fhy', 'age' => '22');handJsonp($data);//处理jsonpfunction handJsonp($data){ $callback = $_GET['callback'] ? : 'callback'; //默认使用callback echo sprintf("%s(%s)", $callback, json_encode($data)); exit;}一旦请求成功,服务端输出了:
Copyhandler({name: "52fhy", age: "22"});这时候浏览器就要响应了,找到handler()方法并执行,恰好,我们提前定义好了handler()方法 。
这里为什么服务端没有限制访问呢?原因是我们通过动态添加了个:
Copy<script src=https://www.isolves.com/it/cxkf/bk/2019-08-30/"http://demo.52fhy.com/jsonp/handJsonp.php?callback=handler">它的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来 。
这种方法就是JSONP 。
使用jQuery/Zepto如果使用jQuery/Zepto,JSONP的方式将会和发送非跨域请求那样简单 。
示例:
Copy$.ajax({ type: "get", async: false, url: "http://demo.52fhy.com/jsonp/handJsonp.php", dataType: "jsonp", success: function (data, textStatus, jqXHR) { console.log(data); }, error: function (XMLHttpRequest, textStatus, errorThrown) { alert('fail'); console.log(XMLHttpRequest, textStatus, errorThrown); }});
推荐阅读
- Java 线程池 ThreadPoolExecutor 八种拒绝策略浅析
- 浅析凉茶的历史及起源
- Android系统架构浅析
- 浅析浏览器缓存
- 浅析普洱熟茶各种不正常味道的原因
- FLV协议5分钟入门浅析
- 锁寂峨眉春欲绝,心上愁云千重叠;春词七首,浅析如何填作蝶恋花
- 浅析紫砂陶生产工艺
- 浅析scrapy与scrapy_redis区别
- 三种不同风格的紫砂器浅析