Ajax跨域问题的jsonp解决方案javascript
在前端咱们常常会使用Ajax来向服务器发送请求和接收服务器响应回来的数据,通常来讲在同一个服务器的数据来往是没有什么问题的,可是有时使用Ajax请求数据并不局限于同一个服务器,跨服务器请求就会遇到跨域问题,下面咱们探讨一下跨域问题是怎么产生的,最优的解决方案是什么?php
同源策略是浏览器的一种安全策略,是为了保护本地数据不被从其余服务器获取回来的数据污染,从而拒绝接受非本服务器响应回来的数据.这样的后果就是咱们能成功的向其余的服务器发送数据请求,对方也能成功响应并返回数据,html
可是,就是没有办法接受数据,由于浏览器拦截了.前端
这里解释一下"同源"的概念:java
协议,域名,端口都一致视为同源,有其中一个不一样则为不一样源jquery
上面已经解释了什么是同源,能够理解为同源即同域,若是在非同源的基础上,想要进行数据来往,这时就会出现咱们所说的跨域问题web
一共有六种方案:ajax
注意:我下面要讲的解决方案是jsonp
,在讲jsonp
以前我先讲基础的同源的jQuery的Ajax的写法json
phpstudy
api
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="http://lib.sinaapp.com/js/jquery/2.0.2/jquery-2.0.2.min.js"></script>
</head>
<body>
<button class="btn">获取数据</button>
<script type="text/javascript"> $(function() { $(".btn").click(function() { $.ajax({ type: "get", url: "./data.php", dataType:"json", success: function(data) { //var data=JSON.parse(data); console.log(data.username);//zhangsan console.log(data.age);//12 }, error: function() { console.log("获取失败"); } }); }) }) </script>
</body>
</html>
复制代码
<?php
$arr=["username"=>"zhangsan","age"=>12];
echo json_encode($arr);
?>
复制代码
运行结果
上面的代码在同源的状况下可以成功请求到data.php,并成功打印出数据
//jQuery中通常不须要json数组转化为对象,只须要指定数据的类型是json类型便可
dataType:"json"//默认为文本型
复制代码
为了实现Ajax的跨域请求,须要将上面例子的基础上,将index.html文件中Ajax请求的路径改成不一样域名的网站,我在phpstudy环境中映射了一个目录并指定一个域名,下面的例子咱们就来跨域访问该目录下的data.php文件
修改index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="http://lib.sinaapp.com/js/jquery/2.0.2/jquery-2.0.2.min.js"></script>
</head>
<body>
<button class="btn">获取数据</button>
<script type="text/javascript"> $(function() { $(".btn").click(function() { $.ajax({ type: "get", url: "http://www.web2.com/data.php", dataType:"json", success: function(data) { //var data=JSON.parse(data); console.log(data.username);//zhangsan console.log(data.age);//12 }, error: function() { console.log("获取失败"); } }); }) }) </script>
</body>
</html>
复制代码
data.php文件
<?php
$arr=["username"=>"zhangsan","age"=>12];
echo json_encode($arr);
?>
复制代码
运行结果
从上面的结果来看,跨域请求数据成功,对方响应也成功了,可是被浏览器拦截了,这就是典型的跨域问题
下面咱们来解决这个问题,并能在前台成功读取返回来的值
jsonp这种解决跨域问题方案一共有两种方法
在前端的页面中将跨域的请求的URL赋值给script标签的src属性
<script src="http://www.web2.com/data.php"></script>
复制代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="http://lib.sinaapp.com/js/jquery/2.0.2/jquery-2.0.2.min.js"></script>
</head>
<body>
<button class="btn">获取数据</button>
<script src="http://www.web2.com/data.php"></script>
<script type="text/javascript"> $(function() { $(".btn").click(function() { console.log(temp); }) }) </script>
</body>
</html>
复制代码
data.php
<?php
//echo "var temp=111";//传单个值
$arr=["username"=>"zhangsan","age"=>12];//项目中经常传数组
$arr=json_encode($arr);
echo "var temp=".$arr;
?>
复制代码
不难发现这种传值的方式有些麻烦,下面介绍动态建立script标签,经过标签的src属性进行跨域请求
原生js写法
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="http://lib.sinaapp.com/js/jquery/2.0.2/jquery-2.0.2.min.js"></script>
</head>
<body>
<script type="text/javascript"> //动态建立 var script=document.createElement("script"); script.src="http://www.web2.com/data.php?callback=gdata"; var head=document.getElementsByTagName('head')[0]; head.appendChild(script); function gdata(data){ console.log(data.username); console.log(data.age); } </script>
</body>
</html>
复制代码
data.php
<?php
$arr=["username"=>"zhangsan","age"=>12];
$arr=json_encode($arr);
$cb=$_GET['callback'];
echo $cb.'('.$arr.')';//调用回调函数,注意拼接的方式,
?>
复制代码
注意: 在上面的这种方法中,回调函数名字默认是callback,JQuery官方文档有说明,固然也能够是其余名字,这个名字由后台人员定义,再告诉前端人员,不然前端人员将没法使用正确的回调函数名获取值 咱们知道,在实际的项目中,咱们常常使用的是jQuery的写法
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="http://lib.sinaapp.com/js/jquery/2.0.2/jquery-2.0.2.min.js"></script>
</head>
<body>
<button class="btn">获取数据</button>
<script type="text/javascript"> $(function() { $(".btn").click(function() { $.ajax({ type: "get", url: "http://www.web2.com/data.php", dataType:"jsonp",//注意类型为jsonp success: function(data) { console.log(data.username);//zhangsan console.log(data.age);//12 }, error: function() { console.log("获取失败"); } }); }) }) </script>
</body>
</html>
复制代码
到此为止,咱们就讲完了Ajax跨域请求的jsonp解决方案,可是在实际的调用别人的api时还会有其余要注意的问题,好比须要在发送请求时同时将使用api的密钥发送过去