为什么返回的数据前面有callback?
这是一个同学出现的问题,问到了我。
应该是这样的:
但问题是这样的:
我看了所请求的格式和后台要求的也是相同的。而且我也是这种做法,为什么他的就不行呢?
打了几遍 JSON.parse 也都是不行……然后也不知道什么情况的耿耿于怀的回去了。
后来在网上搜索,结果都不是想要的。
把 callback 字符串截取掉,这个就不用说咯。这是一种把 json 弄出来的方法。但并不是要问的问题。要问的是:
为什么返回的数据前面会加上 callback ,括号里才是 json 内容。
知乎相似问题:
调用一个api,返回数据格式是:jsonCallback(括号里面才是json),该怎么处理?
百度知道相似问题:
如何在这组返回的数据中获取data对应字符串中jsonCallBack函数并通过其调用?
var jsonback = function (json) { return json; }; var jsonObj = eval(obj.data); //或 var jsonStr = JSON.parse(obj.data.match(/^jsonback\((.*)\);$/)[1]);
csdn相似问题:
关于jsonp返回回来的数据怎么解析
jQuery18307755723037111298_1402151229915([{ "list": [{ "id": 1, "title": "title 1" }, { "id": 2, "title": "title 2" }, { "id": 3, "title": "title 3"}] }])
//jq的代码是这样子的 function loadInfo() { var url = "http://192.168.100.101:81/A.aspx"; $.ajax({ type: "get", async: true, url: url, dataType: "jsonp", jsonp: "callback", //服务端用于接收callback调用的function名的参数 success: function(data) { alert(data.list); //这个地方报错是,不是一个函数 }, error: function() { alert("error"); } }); }
就没几个人回答 “为什么”,最多都在说 “怎么做”?
好吧。通过自己的研究。发现问题是这样的:
如果把 dataType:"jsonp" 的 dataType 写错,就会出现这种情况。其实也相当于没有传 dataType 这个参数。
但是如果把 "jsonp" 写错,就触发请求失败的函数了 error:function(){} 。
那么问题又来了,像上面 csdn 中的 dataType 好像没写错哟,那返回那样的数据格式 jQuery...([]) 是什么鬼?我想,可能 () 括号前面的 jQuery... 就像 上面其他情况中的 callback、jsonback 一样,相当于一种名字吧。 jsonp 和 json 是与之对应的。但 jQuery... 就不知道要如何与之对应了。所以就解析不了。
扩展阅读:
$.getJSON()方法跨域 去取得服务器的json对象的时候,url的后缀最后带一个"callback=?"的参数作为成功的回调函数;如:
var url = "${BIPJS}/intf/accountsOfRefuseEmail.jsp?act=add&siteId=${LANG.siteId}&accountId=${loginId}&callback=?"; $.getJSON(url, {} , function(data) { var code = data.code; if(code == 0){ $('#floatOne').myFadeIn(); } });
此时返回的data是一个json对象;相应地,服务器返回字符串应该要这种样式:
String callback = T.stringValue(getRequestParams(request,"callback"),""); JSONObject jo = new JSONObject(); // put key/value in jo out.print(callback + "(" + jo + ")");
原理:Jquery在解析请求callback=?的时候,会自动生成一个callback=jsonp***的字符串,这个字符串jsonp***在成功回调的时候作为一个方法,被Jquey自动执行,参数是一个json格式的字符串(这里是data)。相应地;服务器返回的字符串要这种形式:jsonp***(JSONObject)。
如:刚上面的url被Jquey解析成:
-
Request URL:http://localhost.pcauto.com.cn:12385/intf/accountsOfRefuseEmail.jsp?act=add&siteId=2&accountId=388&callback=jsonp1381976698163&_=1381976708919
服务器返回的字符串形式:
jsonp1381976698163({"code":0,"msg":"增加用户成功"})
Jquery的回调方法jsonp1381976698163(jsonStr)就是要把字符串jsonStr转换成josn对象,这里就是转换成data这个json对象。
jQuery 会把?注册成window.? 的系统函数,然后映射调用。
一般用于跨域ajax请求,提供URL的一方会返回一个callback函数的JSON数据,然后回调时就能获取了。
请求的URL例子:
"myurl?callback=123123123" //这个123123就是?号,jquery自动生成的。
返回的数据例子:
123123123({“id”:"1","name":"张三"})
js url?callback=xxx xxx的介绍
由于安全的原因,浏览器做了很多方面的工作,由此也就引入了一系列的跨域问题,需要注意的是:
跨域并非浏览器限制了发起跨站请求,而是跨站请求可以正常发起,但是返回结果被浏览器拦截了。最好的例子是 CSRF
跨站攻击原理,请求是发送到了后端服务器无论是否跨域!注意:有些浏览器不允许从HTTPS的域跨域访问HTTP,比如Chrome和Firefox,这些浏览器在请求还未发出的时候就会拦截请求,这是一个特例
1. JSONP
JSONP
的全称是 "JSON With Padding", 词面意思上理解就是 "填充式的JSON"。它不是一个新鲜的东西,隶属于 JSON
的一种使用方法,或者说是一种使用模式,可以解决一些常见的浏览器端网页跨域问题。
正如他的名称一样,它是指被包含在调用函数中的JSON,比如这样:
callback({"Name": "小明", "Id" : 1823, "Rank": 7})
由于 jQuery
的一些原因,使得 JSONP
常常与 Ajax
混淆。实际上,他们没有任何关系。
由于浏览器的同源策略,使得在网页端出现了这个“跨域”的问题,然而我们发现,所有的 src
属性并没有受到相关的限制,比如 img
/ script
等。
JSONP
的原理就要从 script
说起。script
可以执行其他域的js
函数,比如这样:
a.html ... <script> function callback(data) { console.log(data.url) } </script> <script src='b.js'></script> ... b.js callback({url: 'http://www.rccoder.net'})
显然,上面的代码是可以执行的,并且可以在console里面输出http://www.rccoder.net
利用这一点,假如b.js里面的内容不是固定的,而是根据一些东西自动生成的, 嗯,这就是JSONP的主要原理了。回调函数+数据就是 JSON With Padding
了,回调函数用来响应应该在页面中调用的函数,数据则用来传入要执行的回调函数。
至于这个数据是怎么产生的,说粗鲁点无非就是字符串拼接了。
简单总结一下: Ajax 是利用 XMLHTTPRequest 来请求数据的,而它是不能请求不同域上的数据的。但是,在页面上引用不同域的 js 文件却是没有任何问题的,这样,利用异步的加载,请求一个 js 文件,而这个文件的内容是动态生成的(后台语言字符串拼接出来的),里面包含的是 JSON With Padding(回调函数+数据),之前写的那个函数就因为新加载进来的这段动态生成的 js 而执行,也就是获取到了他要获取的数据。
重复一下,在一个页面中,a.html这样写,得到 UserId 为 1823 的信息:
a.html ... src="http://server2.example.com/RetrieveUser?UserId=1823&callback=parseResponse"> ...
请求这个地址会得到一个可以执行的 JavaScript。比如会得到:
parseResponse({"Name": "小明", "Id" : 1823, "Rank": 7})
这样,a.html里面的 parseResponse()
这个函数就能执行并且得到数据了。
等等,jQuery到底做了什么:
jQuery 让 JSONP 的使用API和Ajax的一模一样:
$.ajax({ method: 'jsonp', url: 'http://server2.example.com/RetrieveUser?UserId=1823', success: function(data) { console.log(data) } })
之所以可以这样是因为 jQuery 在背后倾注了心血,它会在执行的时候生成函数替换callback=dosomthing
,然后获取到数据之后销毁掉这个函数,起到一个临时的代理器作用,这样就拿到了数据。
JSONP 的后话:
JSONP的这种实现方式不受同源策略的影响,兼容性也很好;但是它之支持 GET 方式的清楚,只支持 HTTP 请求这种特殊的情况,对于两个不同域之间两个页面的互相调用也是无能为力。
2. CORS
XMLHttpRequest
的同源策略看起来是如此的变态,即使是同一个公司的产品,也不可能完全在同一个域上面。还好,网络设计者在设计的时候考略到了这一点,可以在服务器端进行一些定义,允许部分网络访问。
CORS 的全称是 Cross-Origin Resource Sharing,即跨域资源共享。他的原理就是使用自定义的 HTTP 头部,让服务器与浏览器进行沟通,主要是通过设置响应头的 Access-Control-Allow-Origin
来达到目的的。这样,XMLHttpRequest 就能跨域了。
值得注意的是,正常情况下的 XMLHttpRequest 是只发送一次请求的,但是跨域问题下很可能是会发送两次的请求(预发送)。
更加详细的内容可以参见:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
CORS 的后话:
相比之下,CORS 就支持所有类型的 HTTP 请求了,但是在兼容上面,往往一些老的浏览器并不支持 CORS。
Desktop:
浏览器 | 版本 |
---|---|
Chrome | 4 |
Firefox (Gecko) | 3.5 |
Internet Explorer | 8 (via XDomainReques) 10 |
Opera | 12 |
Safari | 4 |
Mobile:
设备 | 版本 |
---|---|
Android | 2.1 |
Chrome for Android | yes |
Firefox Mobile (Gecko) | yes |
IE Mobile | ? |
Opera Mobile | 12 |
Safari Mobile | 3.2 |
3. window.name
window.name 在一个窗口(标签)的生命周期之内是共享的,利用这点就可以传输一些数据。
除此之外,结合 iframe 还能实现更加强大的功能:
需要3个文件: a/proxy/b
a.html <script type="text/javascript"> var state = 0, iframe = document.createElement('iframe'), loadfn = function() { if (state === 1) { var data = iframe.contentWindow.name; // 读取数据 alert(data); //弹出'I was there!' } else if (state === 0) { state = 1; iframe.contentWindow.location = "http://a.com/proxy.html"; // 设置的代理文件 } }; iframe.src = 'http://b.com/b.html'; if (iframe.attachEvent) { iframe.attachEvent('onload', loadfn); } else { iframe.onload = loadfn; } document.body.appendChild(iframe); </script>
b.html <script type="text/javascript"> window.name = 'I was there!'; // 这里是要传输的数据,大小一般为2M,IE和firefox下可以大至32M左右 // 数据格式可以自定义,如json、字符串 </script>
proxy 是一个代理文件,空的就可以,需要和 a 在同一域下
4. document.domain
在不同的子域 + iframe交互的时候,获取到另外一个 iframe 的 window对象是没有问题的,但是获取到的这个window的方法和属性大多数都是不能使用的。
这种现象可以借助document.domain
来解决。
example.com
<iframe id='i' src="1.example.com" onload="do()"></iframe>
<script>
document.domain = 'example.com';
document.getElementById("i").contentWindow;
</script>
1.example.com <script> document.domain = 'example.com'; </script>
这样,就可以解决问题了。值得注意的是:document.domain
的设置是有限制的,只能设置为页面本身或者更高一级的域名。
document.domain的后话:
利用这种方法是极其方便的,但是如果一个网站被攻击之后另外一个网站很可能会引起安全漏洞。
5.location.hash
这种方法可以把数据的变化显示在 url 的 hash 里面。但是由于 chrome 和 IE 不允许修改parent.location.hash 的值,所以需要再加一层。
a.html 和 b.html 进行数据交换。
a.html function startRequest(){ var ifr = document.createElement('iframe'); ifr.style.display = 'none'; ifr.src = 'http://2.com/b.html#paramdo'; document.body.appendChild(ifr); } function checkHash() { try { var data = location.hash ? location.hash.substring(1) : ''; if (console.log) { console.log('Now the data is '+data); } } catch(e) {}; } setInterval(checkHash, 2000);
b.html //模拟一个简单的参数处理操作 switch(location.hash){ case '#paramdo': callBack(); break; case '#paramset': //do something…… break; } function callBack(){ try { parent.location.hash = 'somedata'; } catch (e) { // ie、chrome的安全机制无法修改parent.location.hash, // 所以要利用一个中间域下的代理iframe var ifrproxy = document.createElement('iframe'); ifrproxy.style.display = 'none'; ifrproxy.src = 'http://3.com/c.html#somedata'; // 注意该文件在"a.com"域下 document.body.appendChild(ifrproxy); } }
c.html //因为parent.parent和自身属于同一个域,所以可以改变其location.hash的值 parent.parent.location.hash = self.location.hash.substring(1);
这样,利用中间的 c 层就可以用 hash 达到 a 与 b 的交互了。
6.window.postMessage()
这个方法是 HTML5 的一个新特性,可以用来向其他所有的window对象发送消息。需要注意的是我们必须要保证所有的脚本执行完才发送MessageEvent,如果在函数执行的过程中调用了他,就会让后面的函数超时无法执行。
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
ajax 跨域请求时url参数添加callback=?会实现跨域问题
例如:
1.在 jQuery 中,可以通过使用JSONP 形式的回调函数来加载其他网域的JSON数据,如 "myurl?callback=?"。jQuery 将自动替换 ? 为正确的函数名,以执行回调函数。 jQuery 会把?注册成window.? 的系统函数,然后映射调用。一般用于跨域ajax请求,提供URL的一方会返回一个callback函数的JSON数据,然后回调时就能获取了。 请求的URL例子:"myurl?callback=123123123" //这个123123就是?号,jquery自动生成的。返回的数据例子:123123123({“id”:"1","name":"张三"}) 2.var url="http://localhost:8080/WorkGroupManagment/open/getGroupById"
+"?id=1&callback=?";
$.jsonp({
"url": url,
"success": function(data) {
$("#current-group").text("当前工作组:"+data.result.name);
},
"error": function(d,msg) {
alert("Could not find user "+msg);
}
});更多详情请查询 https://github.com/rccoder/blog/issues/5
为什么返回的数据前面有callback? ashx/json.ashx?的后面加 callback=? 起什么作用 js url?callback=xxx xxx的介绍 ajax 跨域请求时url参数添加callback=?会实现跨域问题的更多相关文章
-
ajax 跨域请求时url参数添加callback=?会实现跨域问题
例如: 1.在 jQuery 中,可以通过使用JSONP 形式的回调函数来加载其他网域的JSON数据,如 "myurl?callback=?".jQuery 将自动替换 ? 为正确 ...
-
javascript fetch 跨域请求时 session失效问题
javascript 使用fetch进行跨域请求时默认是不带cookie的,所以会造成 session失效. fetch(url, { method: 'POST', credentials: 'in ...
-
SpringMVC处理跨域请求时的一个注意事项
由于公司对SpingMVC框架里面的东西进行了扩展,在配置SpringMVC时没有使用<mvc:annotation-driven>这个标签.而且是自己手动来配置HandlerMa ...
-
SpringMvc+ajax跨域请求时,出现options类型的请求并返回403的解决方案
在使用 $.ajax({ url:'http://127.0.0.1:8081/rest/ccxxx/xxxx', type:'POST', dataType:"json", co ...
-
在用AJAX跨域请求时遇到的问题
刚刚接触ajax就遇到一个词--跨域. 在我百度了各种资料以后总结了一句话:“只要不是在一个协议.域.名端口下,都属于跨域(127.0.0.1本地也属于跨域)”. 在做ajax请求的时候,请求不到并且 ...
-
ajax跨域请求时,sessionId不一样,导致无法记住登陆状态
遇到这样一个场景,就是前端的域是dev,请求接口时,接口的域是beta,即使在服务端设置了cookie存放的域,'COOKIE_DOMAIN' => '.roboming.com',虽然c ...
-
关于.Net Core 前后端分离跨域请求时 ajax并发请求导致部分无法通过验证解决办法。
项目中有这样一个页面.页面加载的时候会同时并发6个ajax请求去后端请求下拉框. 这样会导致每次都有1~2个“浏览器预请求”不通过. 浏览器为什么会自动发送“预请求”?请看以面连接 https://b ...
-
jquery ajax在IE9以下进行跨域请求时无效的问题
第一步:设置浏览器安全属性,启用[通过域访问数据源]选项: 1.选择Internet选项 2.选择安全---自定义级别 3.找到其他---通过域访问数据源,选择启用,然后确定就可以了. 第二步:调用a ...
-
跨域请求 &; jsonp
0 什么是跨域请求 在一个域名下请求另外一个域名下的资源,就是跨域请求.example 1:比如:我当前的域名是http://che.pingan.com.我现在要去请求http://www.cnbl ...
随机推荐
-
Windows下配置nginx根目录的问题
location / { root E:/xampp/htdocs/html5/php/yii2-rest-master/rest/web; index index.html index.htm; } ...
-
8.Smack类库
1.登陆IM Connection.DEBUG_ENABLED = true;//首先激活调试模式 1.1建立连接 首先,在启动DSM Message时,客户端通过XMPPConnection与服务器 ...
-
C# Winform常见的Editor
常见Editor: 1)ArrayEditor,继承自CollectionEditor 2)BinaryEditor 3)CollectionEditor 4)DateTimeEditor 5)Mul ...
-
服务器time_wait状态原因
通信双方建立TCP连接后,主动关闭连接的一方就会进入TIME_WAIT状态 TIME_WAIT状态的时间是2倍的MSL(最大生存时间),在TIME_WAIT状态TCP连接实际上已经断掉,但是该插口又不 ...
-
TopCoder SRM500 Div1 250 其他
原文链接https://www.cnblogs.com/zhouzhendong/p/SRM500-250.html SRM500 Div1 250 题意 (看题用了半个小时--) 有 n 个人(编号 ...
-
gdb调试常用实用命令和core dump文件的生成(转)
1.生成core dump文件的方法: $ ulimit -c //查看是否为0 如果为0 $ ulimit -c unlimited 这样在程序崩溃以后会在当前目录生成一个core.xxxx的 ...
-
Springboot 上传excel并解析文件内容
最近在做一个物业的系统,需要通过excel上传业主的信息,解析并入库. 参考:https://www.cnblogs.com/jyyjava/p/8074322.html 话不多说,直接上核心代码 i ...
-
C#发起HTTP请求
浏览器能看到的数据 用后端模拟请求都能获取到 如果拿不到 看看是不是请求参数哪里没设置 刚好服务器检查了这个参数 string url = ""; string para = ...
-
JDK7与JDK8中HashMap的实现
JDK7中的HashMap HashMap底层维护一个数组,数组中的每一项都是一个Entry transient Entry<K,V>[] table; 我们向 HashMap 中所放置的 ...
-
你写的什么垃圾代码让Vsync命令不能及时处理呢?(2)
接上篇 1.TraceView Traceview看起来复杂,其实很简单: 上部分图中,X代表时间消耗,Y轴代表各个线程中的方法,且使用了不同颜色表示.面积越款,时间越长. 下部分为分析面板,分析面板 ...