本文目录一览:
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 解析器解析。