目前主流的前端跨域請求方式有兩種,一種是XHR2 CORS,也就是在服務端填上響應頭:
header(“Access-Control-Allow-Origin:*”);
/星號表示所有的域都可以接受,/
header(“Access-Control-Allow-Methods:GET,POST”);
CORS不支持ie10以下。但是
第二種是更加方便的就是jsop了,jsop有很多種實現方式,除了原生的 js script jsop之外,其他支持jsop的框架也都能完成。我今天主要就是講一講自己在使用jquery jsop時碰到的坑以及jquery ajax和jquery jsop 的區別。
首先請看我的demo:
//ajax方法
function total_tendency() {
$.ajax({
url: "/count/storage/data?callback=storageSurvey",
dataType: "jsonp", //指定服務器返回的數據類型爲jsonp
type: "GET",
async:true,
jsonp: "callback", ///指定參數名稱,默認爲callback
jsonpCallback:"storageSurvey", //指定回調函數名稱
success: function (data) {
storageSurvey_local(data);
},
error:function () {
alert("error");
}
}
function storageSurvey_local(data) {
//將後臺返回的數據先進行base64解碼,再轉換成json格式。
function decode(rtnData){
var dstr = kvcommon.base64Decode(rtnData);
var rtnData = kvcommon.Ajax.Str2Json(dstr);
return rtnData;
}
var now_data = decode(data);
var json = now_data[0];
console.log(now_data);
if(json.status == 0) {
var length = json.len;
modules = {};
//數據渲染
var modules = json.storage;
var max_count = json.max_count;
//在model_add()這個方法裏進行數據獲取和渲染
model_add(length,modules,max_count);
}
}
在total_tendency( )這個函數裏的ajax中我使用的ajax裏可以看到,所有加了註釋的地方都是與普通ajax傳json數據不一樣的地方。
只有這些不同嗎?當然不是的,網上很多都說ajax和jsop不能歸結爲一種東西,事實上也正是如此,爲什麼這麼說?請看如下代碼:
//ajax方法
function total_tendency() {
$.ajax({
url: "/count/storage/data?callback=storageSurvey",
dataType: "jsonp", //指定服務器返回的數據類型爲jsonp
type: "GET",
async:true,
jsonp: "callback", ///指定參數名稱,默認爲callback
jsonpCallback:"storageSurvey", //指定回調函數名稱
success: function (data) {
//把success裏調用的函數改爲回調函數名。
storageSurvey(data);
},
error:function () {
alert("error");
}
}
function storageSurvey(data) {
// 調用次數測試
alert("test");
//將後臺返回的數據先進行base64解碼,再轉換成json格式。
function decode(rtnData){
var dstr = kvcommon.base64Decode(rtnData);
var rtnData = kvcommon.Ajax.Str2Json(dstr);
return rtnData;
}
var now_data = decode(data);
var json = now_data[0];
console.log(now_data);
if(json.status == 0) {
var length = json.len;
modules = {};
//數據渲染
var modules = json.storage;
var max_count = json.max_count;
//在model_add()這個方法裏進行數據獲取和渲染
model_add(length,modules,max_count);
}
}
再將ajax success中調用的函數名改爲回調函數名後,在此函數中加入一個alert(“test”),執行後發現test彈出了兩次。也就是說storageSurvey( )這個函數執行了兩次。再看下面這這段代碼:
//ajax方法
function total_tendency() {
$.ajax({
url: "/count/storage/data?callback=storageSurvey",
dataType: "jsonp", //指定服務器返回的數據類型爲jsonp
type: "GET",
async:true,
jsonp: "callback", ///指定參數名稱,默認爲callback
jsonpCallback:"storageSurvey", //指定調用的回調函數名稱
/* success: function (data) {
//把success裏調用的函數改爲回調函數名。
storageSurvey(data);
},
error:function () {
alert("error");
}*/
}
function storageSurvey(data) {
// 調用次數測試
alert("test");
//將後臺返回的數據先進行base64解碼,再轉換成json格式。
function decode(rtnData){
var dstr = kvcommon.base64Decode(rtnData);
var rtnData = kvcommon.Ajax.Str2Json(dstr);
return rtnData;
}
var now_data = decode(data);
var json = now_data[0];
console.log(now_data);
if(json.status == 0) {
var length = json.len;
modules = {};
//數據渲染
var modules = json.storage;
var max_count = json.max_count;
//在model_add()這個方法裏進行數據獲取和渲染
model_add(length,modules,max_count);
}
}
將success和error屏蔽,執行代碼,有意思的是test還會彈出來,不過只彈出來了一次,意味着storageSurvey( )這個函數這次只執行了一次。
看出jsop與ajax的區別了嗎?如果是ajax,你把在success中調用的函數屏蔽掉,它還會執行嗎?顯然不會!那麼在jsop中爲什麼會執行呢?原因就是這句話:
jsonpCallback:”storageSurvey”,
這句屬性的設置。它本意是設置請求url中callback=後面那個回調函數的名稱,但有意思的是,如果你在此ajax函數外的js中重寫了這麼一個函數,ajax就會直接調用此函數。jquery jsop的這個功能應該是基於原生的js調用jsop的方法,而原生js實現jsonp跨域也更能讓大家理解jsonp實現跨域的原理。看下面這段代碼:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
function connect_data(data){
alert("age:" + data.age + "name:" + data.name);
}
</script>
<script type="text/javascript" src="jquery-1.8.3.min.js">
</script>
<script type="text/javascript" src="這裏寫服務器端調用此函數的文件路徑"></script>
</body>
</html>
然後只需在服務器端以connect_data( ) 命名的函數中返回json數據即可,如有需要,也可自行選擇加密方式,就如我在一開始的demo中用的就是base64decode。
從上面的這個demo中可以看出,jsonp的跨域原理就是利用了src可以避開同源策略這一特性,在原生js中需要手動包裹一層script,在src裏放請求路徑,在路徑裏的文件中傳輸jsop數據。而jquery jsonp則自動動態的給你包裹了一層script標籤和src屬性。
補充: