浏览 5225 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-09-01
最后修改:2011-09-01
最近在做一个webim项目,涉及到多点登陆的功能开发。该功能的核心是跨页面通信,最常用的手段当然是Flash的localConnection。大家都知道,使用LocalStorage进行同域下的跨页面通信是非常容易实现的,但是LocalStorage是针对所有页面生效的,如果考虑存在多个页面时希望可以进行点对点通信、数据组发等,事情就变得有点复杂了。 考虑多点登陆需求中最常见的场景:访客可以打开多个页面,但同时只有一个页面保持与服务器连接;当另一个页面获得焦点时,当前正与服务器保持连接的页面应当断开该连接,并将页面状态传递给获得焦点的页面,新页面立即与服务器建立连接。 为了实现以上场景,这个多点登陆模型应当具备以下基本特征: 在以上场景中,假设我们称“当前正与服务器保持连接的页面”为“活动页面(MainPage)”,其他页面为“非活动页面(SubPage)”,则任意时刻MainPage只有一个,其他页面均为SubPage; 任意一个SubPage应当可以使自己成为MainPage,同时原来的MainPage则转换为SubPage; MainPage和SubPage之间可以传递数据。 我们期望这个模型可以完全隐藏实现方案,从通信的角度来说我更希望该模型能提供如下功能: 页面A可以向发送一个Ajax请求发送Post一样,向页面B发送一个请求,可以携带参数,并允许获取页面B的返回数据以执行回调,例如: A.someKindOfSend(B, key, param, callback); 页面B可以添加一个Action用于处理某key标注的请求,并且返回处理结果,类似 B.someKindOfAddListener(key, handler); MainPage可以向所有SubPage发送请求; 在保证基本功能完整性的情况下,该模型对页面通信做了一些限制,以使逻辑最简: SubPage之间无法直接通信; SubPage可向MainPage发送请求,因此如果两个SubPage之间希望通信,应当将其中一个SubPage转换为MainPage。 另外,由于该模型基于LocalStorage封装,因此也应当能提供基本容器方法:add、set、get、remove。出于稳定性考虑,不提供全局查询和清空操作。 综上,该模型的接口可设计为: MultiPageUtil: { //跨页面通信控制 controller : { //检测当前页面是否为活动页面 isMainPage : function(){}, /** *使当前页面转换为活动页面。如果当前页面已经是一个活动页面,则什么也不做 *@param callback{Function} 转换成功后的回调函数 */ active : function(callback){}, /** *对一个来自其他页面的Post事件添加处理器。 *该方法区分来源,即MainPage能监听来自所有SubPage的事件, *SubPage仅能监听来自MainPage的事件。 *@param key {String} 需要监听的属性key *@param handler {Function(e)} 被监听的key的value发生变化时的处理函数。传入参数为onstorage标准事件对象,handler的返回值将作为post请求中callback方法参数中标注事件e的newValue。如果为一个字段指定了多个listener,则该post的请求会收到多次响应。 */ addPostListener : function(callback){}, /** *如果当前页面是一个SubPage,则该方法将向活动页面发送一个请求。 *@param key {String} 请求标志位,类似Ajax请求中的URL *@param value {String} 请求数据,可用于传递请求参数并在对应的事件处理器中通过e.newValue获取 *@param [callback] {Function} 请求响应函数。该函数将接收来自MainPage关于该请求的回复字符串 */ postMainPage : function(callback){}, /** *如果当前页面是一个MainPage,则该方法将向活动页面发送一个请求。 *@param key {String} 请求标志位,类似Ajax请求中的URL *@param value {String} 请求数据,可用于传递请求参数并在对应的事件处理器中通过e.newValue获取 *@param [callback] {Function} 请求响应函数。该函数将接收来自MainPage关于该请求的回复字符串。注意,如果当前存在多个非活动页面,callback将可能被执行多次。 */ postSubPages : function(callback){} }, //封转原LocalStorage处理的工具集 util : { add : function(key, value){}, set : function(key, value){}, get : function(key){}, remove : function(key, value){}, /** *对一个来自localStorage中的某个属性变化事件添加处理器 *支持添加多个处理器 *该方法不区分来源。 *@param key {String} 需要监听的属性key *@param handler {Function(e)} 被监听的key的value发生变化(由基本容器方法触发)时的处理函数,e为storage标准事件对象 */ addListener : function(key, handler) {} } 到此为止,这个模型看起来还算比较可行,不过,在真正用LocalStorage实现时还需要处理一些额外的问题: 1.基本思想:模型通过localStorage的标准事件onstorage来实现跨页面通信,即页面A通过写入特定数据触发页面B的onstorage事件,页面B响应之后再写入数据通知页面A处理结果; 2.浏览器兼容性问题,老生常谈了,包括事件监听器绑定机制、标准事件属性支持程度等; 3.事件筛选:LocalStorage对应的标准事件onstorage,在一个页面中对LocalStorage进行修改时所有页面均会收到该事件,有的浏览器甚至包括LocalStorage的修改者也会受到。因此,需要在存入的key中添加特定的标志位,以防止不应该响应该事件的页面对事件做出错误的处理。(例如,SubPage应当忽略除来自MainPage之外的所有Post请求); 4.LocalStorage全局域字段污染问题:由1可知,Post请求实质仍然是往LocalStorage中写入数据,普通的处理很有可能将用户写入LocalStorage的普通数据覆盖,从而产生污染。可考虑使用特殊字段时间戳标记的方式防止污染。 5.垃圾数据:大量的Post请求如果不进行清理,则会长期滞留在浏览器划分给LocalStorage在该域下的空间内。因此,每一个Post请求在被处理之后,都应当清空用于发送该Post而在LocalStorage中写入的数据;同时,callback、handler等函数是由绑定在onstorage事件的最上层处理器执行的,而callback应当是一次性的,因此执行之后也应当被处理。 相信看到这里各位一定有许多想法,不妨留下您的意见来一起探讨探讨。附件中的代码是该模型的实现,目前的设计还有很多值得优化的地方,代码逻辑写到后期也有些紊乱和冗余...开发环境为Firefox6+、Chrome13。 关于HTML5 localStorage的介绍请参见此处:http://www.webjx.com/web/xindejiqiao-24894_3.html由于未标注出处,实在没找到原作者,敬请见谅咯~ Many 3X! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-09-13
之前做过类似项目,有几点心得分享一下:
一开始我们也考虑使用LocalStorage,但后来放弃了。 最大的原因是当时还是要求支持IE6,只能使用UserData代替LocalStorage。使用UserData实在是有诸多限制: 1,IE6下,UserData一般状况下只能存储128K的数据,如果你做webim,假设要同步用户登录信息,聊天记录与消息数量,IM的用户好友数一多,这点大小就根本不够用了。 2,假设控制同步的信息,还有另外的问题:IE6,只有IE6下,UserData使用中如果发现跨了路径,页面之间是不能共用一个UserData数据的。这点你可以在MSDN上去查。 onstorage事件貌似还存在一些兼容性问题,你可能需要看看这篇文章:http://m.udpwork.com/item/5588.html 如果你做的这个项目打算放弃IE6,IE7用户,倒是可以多试试。 需要注意的地方有这几点: 1,主从切换是否存在延时。 2,多页面同步数据,小心广播风暴阻塞浏览器。(每个页面收到数据,尤其是初始化数据都会运行程序,如果同一事件有太多页面同事处理事件,有可能会造成页面假死) 3,如果要做客户端同步,可能只能有一个页面建立连接,其他页面作为从页面接收数据,否则难以达到同步。 4,注意用户安全问题,这是个很大的坑。 |
|
返回顶楼 | |
发表时间:2011-09-13
pillar0514 写道 之前做过类似项目,有几点心得分享一下:
一开始我们也考虑使用LocalStorage,但后来放弃了。 最大的原因是当时还是要求支持IE6,只能使用UserData代替LocalStorage。使用UserData实在是有诸多限制: 1,IE6下,UserData一般状况下只能存储128K的数据,如果你做webim,假设要同步用户登录信息,聊天记录与消息数量,IM的用户好友数一多,这点大小就根本不够用了。 2,假设控制同步的信息,还有另外的问题:IE6,只有IE6下,UserData使用中如果发现跨了路径,页面之间是不能共用一个UserData数据的。这点你可以在MSDN上去查。 onstorage事件貌似还存在一些兼容性问题,你可能需要看看这篇文章:http://m.udpwork.com/item/5588.html 如果你做的这个项目打算放弃IE6,IE7用户,倒是可以多试试。 需要注意的地方有这几点: 1,主从切换是否存在延时。 2,多页面同步数据,小心广播风暴阻塞浏览器。(每个页面收到数据,尤其是初始化数据都会运行程序,如果同一事件有太多页面同事处理事件,有可能会造成页面假死) 3,如果要做客户端同步,可能只能有一个页面建立连接,其他页面作为从页面接收数据,否则难以达到同步。 4,注意用户安全问题,这是个很大的坑。 ho~只为尝鲜罢了,实际上IE8都无法支持,因为IE8的onstorage事件对象不携带url以外的数据。 广播风暴的话,使用了点对点机制,每个页面中维护一个可接收的来源页面id,非该来源的数据全部丢弃。 问题蛮多的,嘎嘎~ |
|
返回顶楼 | |