浅谈jsonp跨域

基本概念:什么是jsonp,百度了下给我的结果是 json padding(中文意思理解为数据内填充)。那么数据时什么?数据一般我们写程序时需要用到的是json,没用过或不懂的同学在这里我不在阐述,请自行百度。什么是内填充?就是把这个{json:data},填充到函数的内部。没接触jsonp的概念的同学可能很难理解,我也是刚刚学会,下面用代码做演示。

什么是接口:后端程序返回给前端的一个连接,这个连接给前端提供了一个数据接口(我是自己暂时这么理解的)

下面用豆瓣接口为例这就是一个接口https://api.douban.com/v2/book/1220562 打开连接可以看到存储着图书信息的一个非常大的json数据。

{"rating":{"max":10,"numRaters":327,"average":"7.1","min":0},"subtitle":"","author":["[日] 片山恭一"],"pubdate":"2005-1","tags":[{"count":128,"name":"片山恭一","title":"片山恭一"},{"count":60,"name":"日本","title":"日本"},{"count":55,"name":"日本文学","title":"日本文学"},{"count":37,"name":"小说","title":"小说"},{"count":31,"name":"满月之夜白鲸现","title":"满月之夜白鲸现"},{"count":14,"name":"爱情","title":"爱情"},{"count":8,"name":"純愛","title":"純愛"},{"count":8,"name":"外国文学","title":"外国文学"}],"origin_title":"","image":"http://img3.douban.com/mpic/s1747553.jpg","binding":"平装","translator":["豫人"],"catalog":"
      ","pages":"180","images":{"small":"http://img3.douban.com/spic/s1747553.jpg","large":"http://img3.douban.com/lpic/s1747553.jpg","medium":"http://img3.douban.com/mpic/s1747553.jpg"},"alt":"http://book.douban.com/subject/1220562/","id":"1220562","publisher":"青岛出版社","isbn10":"7543632608","isbn13":"9787543632608","title":"满月之夜白鲸现","url":"http://api.douban.com/v2/book/1220562","alt_title":"","author_intro":"","summary":"那一年,是听莫扎特、钓鲈鱼和家庭破裂的一年。说到家庭破裂,母亲怪自己当初没有找到好男人,父亲则认为当时是被狐狸精迷住了眼,失常的是母亲,但出问题的是父亲……。","price":"15.00元"}

什么是跨域:不同的地址不同的,不同的端口直接可以理解为不同的空间,这个不同的空间就是不同的域。例如www.baidu.com和www.taobao.com就是不同的域。由于同源策略,百度的服务器和淘宝的服务器不能直接沟通。

我现在用js ajax本地直接访问豆瓣的接口看看会有什么反应。

 1 function ajax(url,fnSucc,fnFaild){
 2     //1 创建oAjax 对象
 3         if(window.XMLHttpRequest){
 4             var oAjax=new XMLHttpRequest;    
 5         }else{
 6             var oAjax=ActiveXObject("Mircosoft.XMLHTTP");
 7                 
 8         }
 9         //2和电脑建立连接
10         oAjax.open('GET',url+'?t='+new Date().getTime(),true);
11         //3发送请求
12         oAjax.send();
13         //4接受内容返回结果
14         oAjax.onreadystatechange=function(){
15             if(oAjax.readyState==4){
16                 if(oAjax.status==200){
17                     fnSucc(oAjax.responseText);    
18                 }else{
19                     if(fnFaild){
20                         fnFaild(oAjax.status);    
21                     }
22                 }    
23             }    
24         }    
25 }
26 window.onload=function(){
27     oBtn=document.getElementById('btn1');
28     oBtn.onclick=function(){
29         ajax('https://api.douban.com/v2/book/1220562',function(str){
30             console.log(str)
31         })
32     }    
33 }

写好代码后我们点击按钮"btn1",打开谷歌浏览器的js开发者工具看到显示如下:

红色字母的大概意思就是:由于来源不同的域,所以禁止访问。

那么问题来了:我们要怎么突破同源策略来实现跨域访问到我们想要的文件?

解决办法:1分析接口 2利用script标签

https://api.douban.com/v2/book/1220562?callback=getData

分析接口:我们在上面的接口上方加入"?callback=getData"  让接口返回一个函数getData 变成这种形式了:getData({json:data})

;getData({"rating":{"max":10,"numRaters":327,"average":"7.1","min":0},"subtitle":"","author":["[日] 片山恭一"],"pubdate":"2005-1","tags":[{"count":128,"name":"片山恭一","title":"片山恭一"},{"count":60,"name":"日本","title":"日本"},{"count":55,"name":"日本文学","title":"日本文学"},{"count":37,"name":"小说","title":"小说"},{"count":31,"name":"满月之夜白鲸现","title":"满月之夜白鲸现"},{"count":14,"name":"爱情","title":"爱情"},{"count":8,"name":"純愛","title":"純愛"},{"count":8,"name":"外国文学","title":"外国文学"}],"origin_title":"","image":"http://img3.douban.com/mpic/s1747553.jpg","binding":"平装","translator":["豫人"],"catalog":"
      ","pages":"180","images":{"small":"http://img3.douban.com/spic/s1747553.jpg","large":"http://img3.douban.com/lpic/s1747553.jpg","medium":"http://img3.douban.com/mpic/s1747553.jpg"},"alt":"http://book.douban.com/subject/1220562/","id":"1220562","publisher":"青岛出版社","isbn10":"7543632608","isbn13":"9787543632608","title":"满月之夜白鲸现","url":"http://api.douban.com/v2/book/1220562","alt_title":"","author_intro":"","summary":"那一年,是听莫扎特、钓鲈鱼和家庭破裂的一年。说到家庭破裂,母亲怪自己当初没有找到好男人,父亲则认为当时是被狐狸精迷住了眼,失常的是母亲,但出问题的是父亲……。","price":"15.00元"});

可以看到我们把{json:data}添加到了getData()的内部,把一个大json当做参数传入了getData();这就是所谓的:json padding,json数据内填充

利用script标签实现跨域:

你自己可以试验下用script标签 src="这里是你填写的地址",可以在你的本地文档里加载任何网站的地址(只要这个地址存在并且没有挂掉)。好,那么我就用这个script标签实现跨域。用行话说就是:script标签不受同源策略的影响。

下面看代码:

 1 //数据加载进来时候调用的函数
 2 function getData(data){
 3         var dataLen=data.tags.length;
 4         var oBody=document.getElementsByTagName('body');
 5         var content=document.getElementById('content');
 6         var oHtml='';
 7         for(var i=0;i<dataLen;i++){
 8             var count=data.tags[i].count;
 9             var name=data.tags[i].name;
10             var title=data.tags[i].title;
11             var oStr='count:'+count+'  '+'name:'+name+'  '+'title:'+title+'</br>';
12             oHtml+=oStr
13         }
14         content.innerHTML=oHtml;
15 }
16 window.onload=function(){
17     var oBtn=document.getElementById('btn1');
18     oBtn.onclick=function(){
19         //点击按钮时候创建script标签
20         var oScript=document.createElement('script');
21         oScript.src="https://api.douban.com/v2/book/1220562?callback=getData";
22         var ohead=document.getElementsByTagName('head')[0];
23         ohead.appendChild(oScript);
24         
25     }    
26 }

在上面的代码中我们首先利用DOM创建了一个script标签,第二部把script标签的src赋上接口的地址,在地址上填写上callback回调函数getData.最后我们在全局作用域里声明一个全局函数function getData(data){console.log(data)}

这个全局函数的作用就是,在点击按钮的时我们创建script标签,把内容加载进来,也就是getData({json:data})。在加进来的一瞬间立即执行function getData(data){console.log(data)}

这个过程就城为jsonp跨域。

可以看到谷歌js开发者平台显示数据已经请求成功了。

 

原文地址:https://www.cnblogs.com/ollie-sk8/p/4065151.html