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的密鑰發送過去