本文目錄一覽:
jsonp跨域的原理是什麼?
jsonp其核心思想是利用JS標籤裡面的跨域特性進行跨域數據訪問,在JS標籤裡面存在的是一個跨域的URL,實際執行的時候通過這個URL獲得一段字元串,這段返回的字元串必須是一個合法的JS調用,通過EVAL這個字元串來完成對獲得的數據的處理。
JSONP(JSON with Padding(填充))是JSON的一種「使用模式」,可用於解決主流瀏覽器的跨域數據訪問的問題。
JSONP是一個非官方的協議,它允許在伺服器端集成Script tags返回至客戶端,通過javascript callback的形式實現跨域訪問(這僅僅是JSONP簡單的實現形式)。
相關信息:
由於瀏覽器同源策略的限制,非同源下的請求,都會產生跨域問題,jsonp即是為了解決這個問題出現的一種簡便解決方案。
同源策略即:同一協議,同一域名,同一埠號。當其中一個不滿足時,我們的請求即會發生跨域問題。
jsonp原理,以及為什麼不是真正的ajax
其實原理很簡單,就是利用瀏覽器可以動態地插入一段js並執行的特點完成的。
script
function injectJs(jsUrl) {
var script = document.createElement(‘script’);
script.src = jsUrl;
document.head.appendChild(script);
}
/script
這樣,我們調用injectJs(‘js/abc.js’)瀏覽器就會去載入js/abc.js 並執行它。
比如我們在前端的某個script裡面定義好一個函數:
script
function print(msg) {
console.log(msg);
}
injectJs(‘js/abc.js’);
/script
然後我們在js/abc.js裡面寫上:
print(“hello, world!”);
那麼調用injectJs(‘js/abc.js’)就會輸出hello, world!。
到此為止這些知識點都並不奇怪哈。然後比較猥瑣的知識點來了:我們可以injectJs(‘/abc.php’),並讓php來生成js代碼!比如在abc.php里這樣寫:
?php
header(‘Content-Type: text/javascript’);
echo “print(‘hello, world!’)”;
?
得到跟上面相同的效果!
我們甚至可以這樣帶上get參數:injectJs(‘/abc.php?userId=123’);然後php里取到參數:
?php
header(‘Content-Type: text/javascript’);
$userId = $_GET[‘userId’];
$userName = getUserNameById($userId);//這裡就是個示意,並沒有這個函數
echo “print(‘hello, ” . $username . “!’)”;
?
然後就可以傳不同的參數,得到不同的值啦!
jsonp其實是在這個方式上面又做了一個約定,為了更加通用,要求js傳一個callback函數的名字(我們這個例子就是’print’),然後php端就不必寫死成調用print啦!
比如
script
function print(msg) {
console.log(msg);
}
injectJs(‘abc.php?callback=printuserId=123’);
function test(a) {
console.log(“test – ” + a);
}
injectJs(‘abc.php?callback=testuserId=123’);
/script
在php端:
?php
header(‘Content-Type: text/javascript’);
$userId = $_GET[‘userId’];
$callback = $_GET[‘callback’];
$userName = getUserNameById($userId);//這裡就是個示意,並沒有這個函數
echo $callback. “(‘hello, ” . $username . “!’)”;
?
然後的然後,我上面為了簡單都用了字元串。其實jsonp約定我們的callback接受的參數都是json對象就像這樣:
script
function printUser(user) {
console.log(user);
}
injectJs(‘abc.php?callback=printUseruserId=123’);
/script
PHP端:
?php
header(‘Content-Type: text/javascript’);
$userId = $_GET[‘userId’];
$callback = $_GET[‘callback’];
$user = getUserById($userId);//這裡就是個示意,並沒有這個函數
echo $callback. “(” . json_encode($user) . “)”;
?
以上。
至於第二個問題嘛。。。我也不知道如何回答,非要說的話,ajax是通過XMLHttpRequest來進行的,而jsonp?其實就是載入javascript腳本。。。如果你會前端調試,可以用F12打開瀏覽器的調試窗口,查看網路請求,然後按照xhr或者scripts類型過濾一下,你會發現xhr(XMLHttpRequest的縮寫,也就是所謂的ajax請求)里找不到頁面發送的jsonp請求。反而是在scripts里能找到。為啥?因為jsonp真的就是載入了javascript腳本而已啦。
如何用原生js發送jsonp請求
// 引入進去
script
function ajax(options) {
options = options || {};
options.type = (options.type || “GET”).toUpperCase();
options.dataType = options.dataType || ‘json’;
options.async = options.async || true;
options.timeout=options.timeout||8000;//超時處理,默認8s
var params = getParams(options.data);
var timeoutFlag=null;
var xhr;
var that=this;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveXObject(‘Microsoft.XMLHTTP’)
}
xhr.onreadystatechange = function() {
if(options.dataType === ‘json’){
if (xhr.readyState == 4) {
window.clearTimeout(that.timeoutFlag);
var status = xhr.status;
if (status = 200 status 300) {
// 如果需要像 html 表單那樣 POST 數據,請使用 setRequestHeader() 來添加 http 頭。
options.success options.success(xhr.responseText, xhr.responseXML);
} else {
options.fail options.fail(status);
}
}
} else {
if (xmlHttp.readyState == 4 xmlHttp.status == 200) {
window.clearTimeout(that.timeoutFlag);
var oScript = document.createElement(‘script’);
document.body.appendChild(oScript);
var callbackname = ‘ajaxCallBack’
oScript.src = options.url + “?” + params+’callback=’+callbackname;
window[‘ajaxCallBack’] = function(data) {
options.success(data);
document.body.removeChild(oScript);
};
}
}
};
if (options.type == ‘GET’) {
xhr.open(“GET”, options.url + ‘?’ + params, options.async);
xhr.send(null)
} else if (options.type == ‘POST’) {
xhr.open(‘POST’, options.url, options.async);
if(options.contentType==”undefined”||options.contentType==null){
xhr.setRequestHeader(‘Content-Type’, ‘application/x-www-form-urlencoded’);
xhr.send(params);
}else{
xhr.setRequestHeader(‘Content-Type’, options.contentType);
xhr.send(JSON.stringify(options.data));
}
}
this.timeoutFlag=window.setTimeout(function(){//計時器,超時後處理
window.clearTimeout(that.timeoutFlag);
//options.fail(“timeout”);
xhr.abort();
}.bind(this),options.timeout);
}
function getParams(data) {
var arr = [];
for (var param in data) {
arr.push(encodeURIComponent(param) + ‘=’ + encodeURIComponent(data[param]));
}
return arr.join(”);
}
/script
// 使用
script
ajax({
url: “”, //請求地址
type: ‘GET’, //請求方式
async:true,//同步非同步設置
timeout:8000,//超時設置
data: {
userName:$(“#username”).val(),
phoneNumber:$(“#userphone”).val(),
orderType:’8′,
requirementDetail:”,
method:’homedecapi.decOrder.insertDecOrder’,
orderSource:’無憂居官網PC’
}, //請求參數
success: function(response, xml) {
if(JSON.parse(response).decOrder_insertDecOrder_response){
// alert(“預約成功”)
$(“#mypopup”).css(‘display’,’block’)
}else{
alert(“預約失敗”)
}
},
fail: function(status) {
console.log(‘狀態碼為’ + status); // 此處為請求失敗後的回調
}
});
/script
JSONP是什麼意思
JSONP(JSON with Padding)是JSON的一種「使用模式」,可用於解決主流瀏覽器的跨域數據訪問的問題。由於同源策略,一般來說位於 server1.example.com 的網頁無法與不是 server1.example.com的伺服器溝通,而 HTML 的script 元素是一個例外。利用 script 元素的這個開放策略,網頁可以得到從其他來源動態產生的 JSON 資料,而這種使用模式就是所謂的 JSONP。用 JSONP 抓到的資料並不是 JSON,而是任意的JavaScript,用 JavaScript 直譯器執行而不是用 JSON 解析器解析。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/283369.html