Jsonp跨域访问
很早之前看过好几篇跨域访问的文章,然后做项目的时候基本没有遇到跨域访问的问题。不过该来的还是会来,前些天终于让我遇到了。于是重温了一下原理这些,再进行实战。于是现在也敢通过实战后的一些理解来和大家分享了。
我们今天主要来分享的就是jsonp的跨域访问。
我们将从这几个方面来分析jsonp跨域访问
- 跨域访问是什么
- json是什么
- jsonp是什么
- 如何进行jsonp跨域访问
1.跨域访问是什么
我们先明白一个概念:同源策略
同源策略是一种浏览器的安全策略,一个脚本不能去执行另一个和他不同源的脚本内容。所谓同源指的是域名,协议,端口三个都要相同。所以当我们通过js获取第三方的数据时(比如通过第三方API获取json数据),,浏览器是不允许我们直接这样做的。所以我们得使用一种技巧去访问不同域,然后获得该域的数据。这个就是跨域访问。
2.json是什么
JSON: JavaScript Object Notation(JavaScript 对象表示法)通过名字我们就大概可以知道是个啥了,json是一种轻量级的数据交换格式,而这个格式又是遵循的js的对象语法。所以个人认为json可以直接看做是js的一个子集。
3.jsonp是什么
jsonp:json with padding 我们来翻译一下就是:用来填充的json数据。咦?为什么要这么叫呢。后面当我们讲到jsonp的原理的时候,你就会知道这样取名字的原因了(题外话:取名字真的是个技术活啊。每次遇到函数,变量比较多,如何取个好名字真的很重要)说人话就是:jsonp就是一种访问数据的非官方传输协议。
4.如何进行jsonp跨域访问
通过前面我们可以知道由于同源策略,我们无法通过ajax直接去访问另一个域名下的文件。那这时我们怎么办,别急,直接不行,我们间接还不行吗。我们仔细想想我们的script标签,它是可以获取任何地方的文件的啊。我们可以通过它来帮我们获取我们想要的东西。具体如何操作呢,我们来看例子吧.
首先我们幻想一下我们获得了数据之后我们要干什么,我们把获取的数据显示在页面上吧。
页面的html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试文件</title>
</head>
<body>
<div>
<h1>显示跨域访问获得的数据</h1>
<div id="show">
</div>
</div>
</body>
</html>
我们再在页面中直接添加js函数来处理数据吧
function show(data)//data参数就是我们从另一个域获取到的数据
{
var node = document.getElementById('show');
p.innerHTML=p.innerHTML="这就是获取到的数据 "+data;
}
我们是直接把获取的数据显示出来
然后我们现在去获取数据,我们再添加一个节点,里面的src就是我们要访问的第三方的url,只是在url后面我们额外添加一个callback参数。
这是整个的代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试文件</title>
</head>
<body>
<div>
<h1>显示跨域访问获得的数据</h1>
<div id="showdata">
</div>
</div>
<script type="text/javascript">
function show(data)//data参数就是我们从另一个域获取到的数据
{
var node = document.getElementById('showdata');
p.innerHTML=p.innerHTML="这就是获取到的数据 "+data;
}
</script>
<script type="text/javascript" src="url?callback=show"></script>
</body>
</html>
大家需要注意的是src="url?callback=show",我们把之前定义的show函数作为callback参数传递给服务器端,这个函数就是一个回调函数,具体过程是这样:
一个前提是我们使用jsonp是需要服务器端来配合的,我们通过url访问到服务器的地址,并且传递了一个callback参数给服务器端,然后服务器端能够接收这个参数,然后将数据以json格式作为show函数的参数传递给它,也就是用json数据来填充这个show函数(现在明白叫jsonp的原因了吧),然后调用这个函数,最后因为这个函数被执行,我们的html中的div中就会显示出获取到的数据。
不过这样可能会显得死板,固定了什么时候调用。我们可以动态生成一个script节点,这样我们就可以在需要数据的时候动态调用了,这样就会更合理。我还是上一下完整代码吧
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试文件</title>
</head>
<body>
<div>
<h1>显示跨域访问获得的数据</h1>
<div id="showdata">
</div>
</div>
<script type="text/javascript">
//data参数就是我们从另一个域获取到的数据
function show(data)
{
var node = document.getElementById('showdata');
p.innerHTML=p.innerHTML="这就是获取到的数据 "+data;
}
function invokeRemoteData()
{
var node=document.createElement("script");
//remoteUrl就是第三方服务器的地址
var url=remoteUrl?callback=show ;
node.setAttribute("src",url);
var head=document.getElementsByTagName("head")[0];
//将创建的script节点添加到head的最后,调用开始
head.appendChild(node);
}
</script>
</body>
</html>
当我们需要获取跨域数据时,直接调用invokeRemoteData函数,html页面中就会显示出获取到的数据。
总结一下,完成jsonp跨域访问所需要做的步骤:
- 创建一个函数,这个函数是用来处理获取到的数据
- 给要访问的远程url添加一个callback参数并将之前创建的处理函数作为callback参数的值
- 可以添加一个方法来动态创建一个script标签以此来动态获取数据
ps:
- 此前提到了回调函数,简单说回调函数就是把该函数当做参数传递给另外一个函数,然后在需要的时候在这个函数中调用传入的回调函数。
- 推荐两篇jsonp讲的很好的博客,廖雪峰ajax 和 随它去吧-jsonp 这两位都是大牛,我的这篇只是我的个人理解,大家可以多看看不同的人写的,然后总结一下
- 还推荐一个跨域访问的方法:就是服务器端代理,先请求服务器,然后服务器端帮你请求需要的文件再response给你。