(三)ajax请求不同源之jsonp跨域
在页面上引入不同域上的JS脚本文件却是可以跨域的,JSONP正是利用这个特性来实现的,下面我们将逐步认识JSONP。
一、初识JSONP
JSON是一种数据交互格式,JSONP是一种非官方跨域数据交互协议。JSONP(json with padding)也叫填充式JSON,是被包含在函数调用中的JSON,可以让网页从别的网站获取资料,即跨域读取数据。
二、JSONP的组成
回调函数和数据。
三、JSONP的格式
callbackFunction({"name":"camille","sex":"male"})
四、JSONP的优缺点
1、优点
它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;
它的兼容性更好,在古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;
在请求完毕后可以通过调用callback的方式回传结果。
2、缺点
它只支持GET请求而不支持POST等其它类型的HTTP请求;
它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
五、JSONP的原理
1、直接引入js文件
A、页面的代码
<script type="text/javascript" src="https://xxx.com.cn/js/test.js"></script>
B、test.js的代码
alert("script方式引入js文件");
页面弹出:script方式引入js文件
2、跨域的js调用本地方法获取数据
A、页面的代码
<script type="text/javascript">
var testCallbackFunc = function(result){
alert("我是本地函数,可以被跨域的test.js文件调用,name: " + result.name);
};
</script>
<script type="text/javascript" src="https://xxx.com.cn/js/test.js"></script>
B、test.js的代码
testCallbackFunc({
"name": "camille",
"sex": "male",
"age": 27});
页面弹出:我是本地函数,可以被跨域的test.js文件调用,name:camille
3、怎么让远程js知道它应该调用的本地函数叫什么名字呢?
可以传一个参数过去告诉服务端“我想要一段调用testCallbackFunc函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来生成js脚本并响应了。
//jsonp回调方法,一定要写在jsonp请求前面
//script默认会把请求回来的内容当成js脚本进行解析运行。
var testCallbackFunc= function (result) {
alert("je suis " + result.name);
};
var scriptsrc ="https://xxx.com.cn/api/getUserInfo?sCallback=testCallbackFunc"; //访问后端接口,得到服务器端生成的被回调函数包裹的JSON数据,js脚本。
var dscript = document.createElement("script");
dscript.setAttribute("src", scriptsrc);
document.getElementsByTagName('head')[0].appendChild(dscript);
在network中查看请求,可以看到服务端返回的数据是这样的。
testCallbackFunc({
"name": "camille",
"sex": "male",
"age": 27
});
接下来,把代码封装一下,以便于与用户界面交互,从而实现多次和重复调用。
4、jQuery如何实现jsonp调用
$.ajax({
url:"https://xxx.com.cn/api/getUserInfo",
async: false,
type: "get", // jsonp模式只有get是合法的
data:{
sUrl: "https://sss.com.cn/page/detail.html"
},
dataType: "jsonp",
jsonp:"sCallback",// 指定回调函数名,与服务器端接收的一致,并回传回来
jsonpCallback:"testCallbackFunc",//自定义jsonp回调函数名称,该方法不用自己写
success:function(result){
//dosomething
},
error:function(){
//dosomething
}
})
JSONP协议的特点就是允许用户给服务端传递一个jsonpCallback参数(如jQuery2030038573939353227615_1402643146875)
服务端返回数据时,会将jsonpCallback的参数值作为函数名来包裹json数据,这样客户端就可以自定义函数处理返回数据了。
A、如果不设置jsonpCallback参数,jQuery会自动帮我们随机生成一个回调函数,类似jQuery2030038573939353227615_1402643146875。每刷新一次页面,该值就会变。在network中查看请求,可以看到服务端返回的数据是这样的。
jQuery2030038573939353227615_1402643146875({
"name": "camille",
"sex": "male",
"age": 27
});
B、如果设置jsonpCallback参数,我们可以自定义一个回调函数testCallbackFunc。在network中查看请求,可以看到服务端返回的数据是这样的。
testCallbackFunc({
"name": "camille",
"sex": "male",
"age": 27
});
jquery内部会转化成
https://xxx.com.cn/api/getUserInfo?sCallback=testCallbackFunc&sUrl=http://sss.com.cn/page/detail.html
然后动态加载
<script type="text/javascript" src="https://xxx.com.cn/api/getUserInfo?sCallback=testCallbackFunc&sUrl=http://sss.com.cn/page/detail.html
"></script>
获取到数据后,jQuery会自动销毁这个全局函数。
5、封装后的简写方式
$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。
$.getJSON("https://xxx.com.cn/api/getUserInfo?sUrl=https://sss.com.cn/page/detail.html&sCallback=testCallbackFunc",
function(result){
//dosomething
});
六、如何处理跨域请求失败?
如果服务器拒绝请求,或者请求地址不正确,参数错误,网络不通,跨域就取不到数据,怎么办?下面介绍3种方案。众所周知,在浏览器中,script标签遇到服务器错误时,会触发onerror事件。
1、如果自己实现jsonp,可以这么做。
var ele = document.createElement('script');
ele.type = "text/javascript";
ele.src = '...';
ele.onerror = function() {
alert('error');
};
ele.onload = function() {
alert('load');
};
document.body.appendChild(ele);
2、如果想用jquery的jsonp
JQuery不会处理此类错误,而是选择“静静地失败”,fail回调不会执行,你的代码也不会得到任何反馈,所以你没有处理这种错误的机会,也无法向用户报告错误。
jQuery.ajaxTransport( "script", function(s) {
if ( s.crossDomain ) {
var script,
head = document.head || jQuery("head")[0] || document.documentElement;
return {
send: function( _, callback ) {
script = document.createElement("script");
script.async = true;
...
script.src = s.url;
script.onload = script.onreadystatechange = ...;
head.insertBefore( script, head.firstChild );
},
abort: function() {
...
}
};
}
});
可以看到script是个局部变量,外部无法取到。但是我们可以根据script标签的位置,动态获取head第一个元素,就可以拿到script,然后添加onerror事件。
function jsonp(url, data, callback) {
var xhr = $.getJSON(url + '?jsoncallback=?', data, callback); // request failed
xhr.fail(function(jqXHR, textStatus, ex) {
/*
* in ie 8, if service is down (or network occurs an error), the arguments will be:
*
* testStatus: 'parsererror'
* ex.description: 'xxxx was not called' (xxxx is the name of jsoncallback function)
* ex.message: (same as ex.description)
* ex.name: 'Error'
*/
alert('failed');
}); // ie 8+, chrome and some other browsers
var head = document.head || $('head')[0] || document.documentElement; // code from jquery
var script = $(head).find('script')[0];
script.onerror = function(evt) {
alert('error'); // do some clean // delete script node
if (script.parentNode) {
script.parentNode.removeChild(script);
}
// delete jsonCallback global function
var src = script.src || '';
var idx = src.indexOf('jsoncallback=');
if (idx != -1) {
var idx2 = src.indexOf('&');
if (idx2 == -1) {
idx2 = src.length;
}
var jsonCallback = src.substring(idx + 13, idx2);
delete window[jsonCallback];
}
};
}
3、修改jquery源码,加上onerror事件。
(三)ajax请求不同源之jsonp跨域的更多相关文章
- (三)ajax请求不同源之cors跨域
一.基本原理 CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)它允许浏览器向跨源服务器,发出 XMLHttpReque ...
- (三)ajax请求不同源之websocket跨域
WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀.该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信. 一.WebSocket目标 在一个单独的 ...
- (三)ajax请求不同源之nginx反向代理跨域
一.基本原理 nginx是一个高性能的web服务器,常用作反向代理服务器.nginx作为反向代理服务器,就是把http请求转发到另一个或者一些服务器上. 用nginx反向代理实现跨域,是最简单的跨域方 ...
- (三)ajax请求不同源之服务器代理跨域
一.基本原理 Server Proxy,顾名思义,在服务器端设置一个代理,由服务器端向跨域的网站发出请求,再将请求结果返回给前端,成功避免同源策略的限制. 二.客户端和服务端代码 1.在localho ...
- ajax请求egg用nginx转发跨域问题
火狐浏览器报的 谷歌浏览器报的 前提: npm i egg-cors --save config 文件下的pulgin.js 已经添加 //启用跨域支持 exports.cors = { enable ...
- (二)文档请求不同源之flash跨域
对于FLash,IE是认object标签的,但是FF和Chrome是认embed标签的. 1.客户端 <param name="allowScriptAccess" valu ...
- 深入理解jsonp跨域请求原理
在进行网站开发的过程中经常会用到第三方的数据,但是由于同源策略的限制导致ajax不能发送请求,因此也无法获得数据.解决ajax的跨域问题有两种方法: 一.jsop 二.XMLHttpRequest2中 ...
- Django之jsonp跨域请求原理
在进行网站开发的过程中经常会用到第三方的数据,但是由于同源策略的限制导致ajax不能发送请求,因此也无法获得数据.解决ajax的跨域问题有两种方法: 一.jsonp 二.XMLHttpRequest2 ...
- 深入剖析jsonp跨域原理
在项目中遇到一个jsonp跨域的问题,于是仔细的研究了一番jsonp跨域的原理.搞明白了一些以前不是很懂的地方,比如: 1)jsonp跨域只能是get请求,而不能是post请求: 2)jsonp跨域的 ...
随机推荐
- 计算机网络--差错检测(帧检验序列FCS计算方法)
我们知道数据链路层广泛使用循环冗余检验CRC的检验技术 现在我们知道要发送的数据M=101001(长度为k=6) 在我们每次发送数据的时候需要在M后面添加一个N位的冗余码,一共发送(k+N)位数据 ...
- 学习python第二天
编程语言分为哪几种? 1. 机器语言:是通过直接编写二进制指令对计算机下达指令的编程方式 -- 0000,0000,00000000001:加载 暂存区A 存储器地址1 2. 汇编语言:是通过编写二进 ...
- 剑指Offer_编程题_19
题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2, ...
- 金融量化分析【day110】:NumPy通用函数
一.通用函数 能同时对数组中所有元素进行运算的函数 1.一元函数 1.sqrt 2.ceil 3.modf 4.isnan 5.abs 2.二元函数 1.maxinum 二.数学和统计方法 1.sum ...
- Fiddler--QuickExec
QuickExec在Fiddler中提供了比较快捷的功能服务. 在QuickExec输入框中输入命令,能快速地得到想要的结果. 快捷键:打开Fiddler后,按“Alt+q”,可将光标定位到Quick ...
- DirectX11 With Windows SDK--15 几何着色器初探
前言 从这一部分开始,感觉就像是踏入了无人深空一样,在之前初学DX11的时候,这部分内容都是基本上跳过的,现在打算重新认真地把它给拾回来. DirectX11 With Windows SDK完整目录 ...
- 如何实现Python调用C代码--python与C之间如何通信(swig)
转载: https://www.zhihu.com/question/23003213 1. C代码如何调用Python 1.1 test #include <Python.h> int ...
- EffectiveC++ 第2章 构造/析构/赋值运算
我根据自己的理解,对原文的精华部分进行了提炼,并在一些难以理解的地方加上了自己的"可能比较准确"的「翻译」. Chapter 2 构造 / 析构 / 赋值 条款 05:了解C++ ...
- python 实现简单卷积网络框架
第一步定义卷积核类: class Filter(object): # 滤波器类 对卷积核进行初始化 def __init__(self,width,height,depth): # initializ ...
- Mongodb注入
0x01 Brief Description 作为nosql(not only sql)数据库的一种,mongodb很强大,很多企业也在用到.相对于sql数据库,nosql数据库有以下优点:简单便捷. ...