- 浏览: 425876 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
Glogo:
楼主您好,我在试验您的代码的时候发现新开的三个子线程并没有一直 ...
java 高并发 ReentrantLock -- 可重入的锁 -
univasity:
最近发觉也被限速了,投诉一下就好一会~~ 看来明天又要和电信M ...
ADSL上网速度慢 都是帐号限速惹的祸 -
liuyuanhui0301:
java 高并发 ReentrantLock -- 可重入的锁 -
dang_java:
呵.很好的说明文档.
JXTA技术与应用发展 -
helloqidi:
谢谢,学习了
SQL中exists和in的区别
这篇文章将会探讨一下在网页里做异步的跨域请求,以及借助iframe来获取数据的方法。
呃,本来我觉得这个话题没什么好说的了,因为如今好像没有几个web应用能离开这类request,google和facebook用iframe来做comet的时候也基本上把能hack的都hack遍了,所以我估计开发者社区里应该早就形成所谓的”最佳实践”(best practices)了罢。不过最近看到有一些关注前端技术的blog(比如realazy)在讨论相关的话题,发现还是有一些东西值得写下来。
一、借助script的异步跨域请求
先说跨域的问题,首先要指出的是,iframe里的js宿主对象一样也躲不开同源策略(Same Origin Policy),仅仅能解决二级域名的跨域而已,比如www.tudou.com和so.tudou.com,如果要请求某个八杆子打不到一起去的域名下的数据(例如你想搞mashup),建议老老实实的用script标签去请求JSONP罢。关于JSONP要附带说一下的是,jQuery对JSONP请求的封装方式很值得提倡:
- $.getJSON(url, params + "&jsoncallback=?", function(json){
- /* do something */
- });
用jsoncallback作为服务器端支持的标准jsonp参数,而每次执行这个方法都会用时间戳生成一个唯一的全局函数名,替换这个“?”,这个细节被封装到黑盒里,使用者不必了解,可以像普通的ajax请求一样,用匿名的回调函数作为最末尾的参数(这是jquery强调的风格),这种语法糖(syntactic sugar)的作用绝对不仅仅是让前端开发人员可以偷懒而已,对代码的可读性,兼容性和今后的维护都有好处。(我经常要向服务器端的开发人员解释这个道理,否则他们才不给你支持什么jsoncallback参数呢,直接给你返回一个“yy({……})”就算完工……囧)
二、利用前沿技术的跨域方法
当然了,我们还可以走一些目前来看比较野的路子来实现跨域,比如在页面里嵌入一个不到1K的swf,借助flashplayer向部署了crossdomain.xml的服务器请求数据,再用actionscript里的ExternalInterface类把数据还给javascript(我觉得这种方法忒有调用dll的感觉~大心)。
我们还可以指望ie8里支持的XDomainRequestAllowed,和firefox3.1支持的Access Control,甚至传说中的HTML5 socket……噢喔喔,多么甜美的梦……/掐一把脸蛋
三、用iframe直接发送跨域请求
跟script标签一样,iframe也可以用来替代ajax,而且在修改document.domain之后(比如上面提到的两个域名,可以设置document.domain = “tudou.com”),还可以解决部分跨域问题。
通过iframe请求数据的方法,最直接的莫过于在页面里动态的嵌入一个iframe标签,用它的src属性直接请求包含数据的网页,然后利用那个网页里的js把数据传给父页面,比如:
- <iframe id="crossdomain" width="0" height="0" style="visibility:hidden;" src="http://yoursite.com/request_url/" ></iframe>
这种方法耦合的太紧,非常不推荐。你请求的URI代表一个资源,应该是单纯的数据,它会作为xml,json,js代码还是html来处理,这个并不重要,不应该把你的程序逻辑跟数据混杂到一起,数据也不应该因为跨域或不跨域,用iframe,script还是ajax来请求就变成完全不同的东西。
有人会说:为了让数据能够被JS处理,返回的内容难免有差异。——但是小的差异可以通过合理的封装隐藏起来,比如JQuery的getJSON方法
有人会说:请求的URI是一个动态页面,同样可以在URI里支持类似jsoncallback的参数,生成一个script标签和其中的JS代码,把数据“包裹”在JS里,比如请求“http://yoursite.com/request_url/?callback=cb1304344”,返回:
- <script type="text/javascript">
- document.domain="tudou.com";
- top.cb1304344({ /* 数据 */ });
- </script>
——首先,很多情况下你请求到的不会是动态页面,在这个到处都强调高负载的web世界里,你拿到的经常是squid之类的代理程序返回的缓存。其次,如果你请求的是HTML格式的文本,为了能作为JS代码来执行,服务器端必须对这段文本做转义和清理工作,而且安全性还不一定能保证(因为HTML里经常包含很多来自UGC的内容),如果你请求的是JSON格式的数据……那何必用iframe咧……直接嵌script罢……
四、用iframe直接请求数据的最佳实践
我推荐在上述方法的基础上做改良,首先在服务器端,直接返回数据本身,并且把数据“包裹”在一个textarea标签里,比如:
- <textarea><div><p>yyyyy</p></div></textarea>
textarea的优点是可以支持任何格式的内容,而且这些内容不会在iframe子页面里解析(比如创建DOM树,执行JS),接下来前端要做的,只是在父页面里获取到子页面的DOM,把textarea的内容取出来(注意不能取innerHTML而要取value)。
这里存在一个判断iframe是否加载完成的问题,解决方法之一是在iframe标签上写onload事件,不过这样就需要显式的调用一个函数。
方法二如下:
- (function(){
- try{
- callback(document.getElementById('crossdomain').contentWindow.document.body.getElementsByTagName("TEXTAREA")[0].value);
- }catch(e){
- setTimeout(arguments.callee,0);
- return;
- }
- })();
最后我们可以封装出这样一个方法:
- window.TUI = window.$ = {};
- /**
- * @public 通过iframe异步请求数据
- * @param {string} url是请求的地址
- * @param {function} cb是处理返回数据的回调函数
- */
- TUI.getIframeData = function(url, cb){
- var f = document.getElementById('crossdomain');
- if(f)
- f.src = url;
- else{
- var t = document.createElement("DIV");
- t.innerHTML = '<iframe id="crossdomain" width="0" height="0" style="visibility:hidden;" src="' + url + '" ></iframe>';
- document.body.appendChild(t.firstChild);
- }
- (function(){
- try{
- cb(document.getElementById('crossdomain').contentWindow.document.body.getElementsByTagName("TEXTAREA")[0].value);
- }catch(e){
- setTimeout(arguments.callee,0);
- return;
- }
- })();
- };
- //像这样执行
- $.getIframeData("http://yoursite.com/request_url/", function(data){
- /* do something */
- });
只要再增加一个可选的param参数,这就是一个很标准的jQuery AJAX API,我们还可以在jQuery的$.get上面封装,增加一个是否跨域的判断,当这个request的URI修改成同样的域名后,自动切换到普通的AJAX方法来请求,把返回的文本用类似这样的正则/<(textarea)>(.+)<\/(textarea)>/删掉多余的字符,再传给回调函数,前端和服务器端都不用修改代码。
五、用iframe直接请求数据的缺陷
必须指出的是,iframe在ie里获取数据时会引发一些“小问题”,dojo的创始人Alex Russell把它们称作“灵异点击(phantom click)”和“噩梦般的指示器(throbber of doom)”,前者是指在iframe请求内容的时候会出现一次点击链接的音效(让用户怀疑闹鬼,多差的体验口牙!),后者是指iframe加载过程中,ie的界面上会出现正在读取的提示(比如左下的进度条,右上的图标)……好罢,其实以我个人的标准,这两个问题都可以无视……
这种方法还有一个明显的缺陷,就是只支持GET类型的请求。
六、用iframe结合ajax
不过iframe还有一种使用方法,不但可以避免上面提到的问题,也不需要服务器端做任何调整,简单来说:在iframe的src里调用一个包含ajax方法的页面,然后父页面调用这个方法来发起跟子页面同域名下的ajax请求。在土豆网的播放页面上,我使用这种方法请求用户评论统一接口里的HTML内容,例如这个WH40K:DOWII的视频:
http://www.tudou.com/programs/view/iPcprDz_LhI/
获得评论部分HTML的接口类似这样:
http://comments.tudou.com/itemcomment.srv?method=get&iid=21283123&page=1&tm=5&ban=1
这个接口在独立的一组服务器上实现,在视频播放页,豆单播放页,豆单封面,相册,个人主页都会被调用。由于包含大量用户提交的内容和复杂的HTML结构,如果用JSON形式,前端后端处理起来都效率低,此外,提交新评论,回复,删除,也会用到comments.tudou.com这个域名下的接口,而这些操作显然需要POST类型的请求。在这种需求下,借助iframe的AJAX方法
首先在comments.tudou.com域名下部署一个供iframe调用的跨域文件,感觉很像flashplayer的crossdomain.xml……
http://comments.tudou.com/crossdomain/index.html
可以看到源文件里仅仅包含一个stand-alone的ajax方法……呃……你觉得很眼熟?不用怀疑,就是在jQuery源代码的基础上修改来的-___-b,支持最基本的需求。这个页面可以设置很长的过期头让浏览器缓存起来,因为不会再有变动。
在父页面里通过TUI.videoComment.request提供统一的接口,不做详述了,只列举其中访问跨域方法的部分:
- (function(){
- try{
- $('#crossdomain')[0].contentWindow.TUI.ajax(o);
- }catch(e){
- setTimeout(arguments.callee,500);
- return;
- }
- })();
七、总结一下
iframe适用于 ( 跨域的 && ( 返回大量数据 || 返回HTML内容 || 需要发POST请求 ) ) 的场合,除此之外还有comet里的串流技术(streaming)——本文不涉及。使用时需要注意保持资源的纯粹性,并尽可能隐藏那些跟其他异步请求差异很大的或包含hack的细节(比如嵌入iframe,触发回调函数,处理数据),设计出一致的,兼容性和扩展性良好的,不碍眼的接口XD
关于跨域还要补充一点:修改document.domain可能会产生一些无法预料的问题,比如在firefox里,document.styleSheets的cssRules属性会被拒绝访问。
发表评论
-
如何解决ajax跨域的问题
2009-06-18 18:57 1378ajax(动态网站静态化)伴 ... -
JavaScript对象模型-执行模型
2009-04-12 15:15 845JavaScript对象模型-执行模型 转自:http:/ ... -
使用面向对象的技术创建高级 Web 应用程序
2009-03-26 23:05 908本文讨论: JavaScript 是基于原型的语言 ... -
动态加载javascript
2009-03-26 17:36 1100/** * 动态加载JS文件 */ var ... -
Javascript 的运行及浏览器多线程
2009-03-24 23:51 2066一。本文目的 ... -
Js下对URL字符串的编码与解码
2008-10-27 23:38 1377虽然escape()、encodeUR ... -
深入理解Javascript闭包(closure)(转)
2008-10-21 12:35 870最近在网上查阅了不少Javascript闭包(closure) ... -
在Javascript中,什么是闭包(Closure)
2008-10-21 12:02 975闭包的两个特点:1、作为一个函数变量的一个引用 - 当函数返回 ... -
javascript获取浏览器的宽度和高
2008-09-19 13:55 1912<script language="JavaS ... -
Javascript DOM 编程实例讲解--仿LightBox效果提示框
2008-09-13 11:53 1713Javascript DOM 编程实例讲 ... -
window.open和window.showModalDialog用法
2008-09-05 15:25 1414一、window.open()支持环境: JavaSc ... -
JavaScript中的正则表达式解析
2008-07-10 19:39 925JavaScript的RegExp对象和Str ... -
JS的正则表达式
2008-07-10 19:28 953//校验是否全由数字组成 代码 function isDi ... -
用Javascript评估用户输入密码的强度
2008-07-10 19:25 877密码已经是我们生活工作中必不可少的工具,但一个不安全的密码有又 ... -
JavaScript示例收藏
2008-07-10 18:33 1139JavaScript就这么回事1:基础知识 1 创建脚本块 ... -
javaScript 收藏(1)
2008-07-10 18:33 1071、数字验证内 1.1 整数 ...
相关推荐
在实际开发中,需要根据具体需求和环境选择合适的跨域请求方法。在现代的Web开发实践中,最常使用的是第三种方法,通过在服务器端配置适当的响应头来实现跨域资源共享(CORS),这种方式既安全又高效,也更容易控制...
综上所述,`Default(iframe).rar`压缩包提供的实例展示了如何在.NET环境中利用`iframe`进行页面构建和动态内容加载。通过学习和实践这些文件,开发者可以更好地理解和掌握`iframe`在实际项目中的应用。
在Web开发中,`IFrame`(Inline Frame)和`window`对象是两个非常重要的概念,它们在构建复杂的网页布局和交互中起...在实际项目中,我们还需要考虑跨域安全、性能优化等因素,确保`IFrame`和`window`对象的正确使用。
"Noname1.html"可能是演示IFRAME自适应的一个实例,可能包含了IFRAME元素和相应的CSS或JavaScript代码,用于展示如何实现IFRAME的高度自适应。 总结,IFRAME自适应是创建响应式网页的重要组成部分,它涉及到布局、...
除了JSONP和CORS,还有其他跨域技术,如iframe的`window.postMessage`API,用于在不同源的页面之间进行通信;以及服务器端代理,通过服务器转发请求来规避同源策略。 在实际开发中,选择哪种跨域解决方案取决于应用...
3. postMessage:窗口、iframe间的跨域通信工具。 八、JavaScript安全 1. 防止XSS攻击:对用户输入进行转义或过滤,避免恶意脚本注入。 2. 防止CSRF攻击:通过token验证,确保请求来源合法性。 3. 使用HTTPS:加密...
此外,CORS支持使用通配符和具体域名来限制哪些域可以发起跨域请求。 - document.domain:原理是让不同子域之间的页面设置相同的domain,实现跨域。这通常用于相同主域名不同子域名的情况。 - iframe:可以将一个...
此外,Flash Player的版本也会影响Flex-iframe的兼容性和可用性。 7. **最佳实践与优化** - 为了获得更好的性能和用户体验,尽量优化嵌入的HTML页面,减少不必要的脚本和资源加载。 - 考虑使用沙盒模式以增强安全...
该对象支持同步请求和异步请求,新建一个ajax请求实际就是实例化一个XMLHttpRequest对象。 readystatechange事件 readystatechange事件是一个XMLHttpRequest对象的事件,该事件会在XMLHttpRequest发送一个http请求...
Ajax,全称Asynchronous JavaScript and XML(异步JavaScript和XML),是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。Ajax并非一种独立的新技术,而是利用已有的Web技术组合而成,包括JavaScript...
无刷新文件上传是一种提高用户体验的...它通过异步通信和FormData对象处理文件,提供良好的用户体验,同时需要注意安全性、进度显示和跨域问题。开发者需要根据项目需求和目标用户的浏览器兼容性,选择合适的实现方案。
- iframe+postMessage:通过iframe嵌入跨域页面,并使用postMessage方法在不同的域之间安全地传输消息。 跨域请求的处理,可以使用不同的服务器端语言实现,如PHP、Java、Node.js等,每种语言都有相应的库和工具来...
IFrame(Inline Frame)是一种HTML元素,它允许在网页上嵌入另一个完整的HTML文档,从而实现页面的分层和异步加载。 在ExtJS中,IFrame通常用于实现一些特殊的需求,比如加载外部网页、嵌入表格或其他动态内容,...
14. **跨域通信**:CORS、JSONP、IFrame等解决跨域问题的方法,以及Web Worker和Service Worker在后台处理和离线存储中的应用。 15. **框架与库**:React、Vue、Angular等前端框架,以及jQuery、Lodash等库的使用,...
"z_dialog"插件特别关注这个问题,它可能通过iframe或者Ajax等方式实现跨域数据加载,允许对话框展示来自不同源的内容。 4. **易于使用**:根据描述中的“有demo”,我们可以推测该插件提供了示例代码,这将帮助...
在网页开发中,有时我们需要使用弹出层来展示一些内容,比如进行表单提交、查看详细信息等。...同时,要确保iframe页面与父页面之间有正确的引用关系,以便能够正确地访问和操作父窗口的layer实例。
在JavaScript中,检测一个iframe是否已经完全加载完成是常见的需求,特别是在处理跨域通信、页面嵌套或异步数据加载的场景下。本实例提供的方法是通过JavaScript的事件监听和定时器来实现这一功能。 首先,我们需要...
在本项目中,“隐藏框架实现ajax原理”是一个演示如何利用隐藏iframe来实现Ajax交互的实例。下面我们将详细探讨Ajax的工作原理以及如何通过隐藏框架实现这一过程。 1. **Ajax工作原理**: Ajax的核心是JavaScript...