Archive for the ‘Ajax Patterns’ Category
网页中跨域iframe避免相互刷新死循环的方法
最近在做的系统,需要与客户的网页集成,因此牵涉到了跨域访问的问题。所以使用了大量的iframe绕过浏览器的安全策略。
由于跨域系统的安全限制,这些iframe之间是不能相互通信的,需要靠onload事件和父窗口进行交互,而iframe的刷新动作则须由父窗口控制。
其中遇到了一个有意思的问题。大致是这样的:页面打开时,用户没有登录系统,所有的iframe加载后处于未登录状态,点击任意一个iframe,系统会弹出登录画面,登录系统后,需要重新加载这些iframe,从而实现登录状态的同步。
如下面2张图所示:


于是,我在父窗口中写了这样的jquery脚本:
function refresh() {
__self = $(this);
$('iframe.myDomain').each(function(){
if($(this).attr(id) != __self.attr(id)) {
url = $(this).attr('src');
url = url.replace(/\?rand=.*$/, '?rand=' + Math.random());
$(this).attr('src', url);
}
});
}
$('iframe.myDomain').each(function(){
$(this).bind('load', refresh);
});
每当onload事件发生的时候,refresh函数会被触发,然后就会更新其他的iframe。但是,这样做有个重大的问题!如下图所示,当其他的iframe刷新完成的时候,同样会产生onload事件,此时,refresh再次被触发,又去刷新其他的iframe,产生了连锁反应,整个加载动作陷入了死循环!

为了避免这样的死循环,我们需要让接受到刷新指令的iframe在重新加载页面后不向其他iframe再次发送刷新指令,同时又要让其自身做好接受下一个刷新指令的准备。实现的方法很简单,只要稍稍修改我们的js代码即可。
function noRefresh() {
//不触发任何动作的onload事件处理函数
//重新绑定事件处理函数,为下一次处理onload事件做准备。
$(this).unbind('load');
$(this).bind('load', refresh);
}
function refresh() {
__self = $(this);
$('iframe.myDomain').each(function(){
if($(this).attr('id') != __self.attr('id')) {
url = $(this).attr('src')
url = url.replace(/\?rand=.*$/, '?rand=' + Math.random());
//将待刷新的iframe的onload处理函数重新设置
//其自身刷新后,调用noRefresh,防止刷新事件死循环
$(this).unbind('load');
$(this).bind('load', noRefresh);
//现在,刷新时就不会引起连锁反应了。
$(this).attr('src', url);
}
});
}
$('iframe.myDomain').each(function(){
//初始化的时候,关闭所有的onload事件
$(this).bind('load', noRefresh);
});
OK,问题解决!
