In: 前端开发
18 08 2009呃,好久没更新博客了,一来最近确实比较忙,二来人也变懒了,这样很不好~要改变!
今天要讨论的话题是多页面数据同步。顾名思义,就是更新A页面的内容,B页面也要及时反映出改变,当然A、B页面至少要是在同域下才有意义。放在WebIM这个应用场景中来,就是如果有多个页面开着webim,其中任何一个页面上发送或接收到新消息,要在其他所有的页面中同步显示出来。
使用短连接的WebIM要轮询服务器来获取最新的消息,如果多个页面一起轮询,那么对服务器的消耗还是很大的,使用页面数据同步能减少消耗:无论同时存在多少个聊天页面,同时仅有一个主页面A负责与服务器轮询;在主页面A轮询到服务器消息后,分发给其他页面B、C、D;如果A被关掉了,检测程序会马上检测到,并从剩下的页面中挑选新的页面充当主页面负责通讯;客户端向服务端提交数据不必通过主页面,直接向服务器提交即可,只是提交的数据也需要分发给其他页面,便于同步UI。
多页面数据同步的实现细化起来,大概就是下面这个流程:
1.有一套本地化存储方案,要求能本域下任何页面都可以读写数据,至少有set和get两个方法;
2.页面加载时实例化sync对象,可以指定页面代号(name)方便进行页面分组,系统自动给每个页面分类一个唯一标识符(clientId),并将这个页面client的相关信息加入clients列表,放进本地存储;
3.sync提供sendMsg方法,可根据clientID发给单一页面,或根据name发给一组页面,传递的数据(data)是一个JSON,sendMsg方法不关心data的实际结构。将消息的发送者clientID、接收者clientID以及data拼成一个消息JSON,并将多条JSON组成一个消息数组,序列化后放本地存储;
4.sync通过定时检查并解析本地存储获知是否有新消息,在收到发给自己(根据clientID来判断)的消息后,将这条消息置为已读,并调用onNewMsg方法,将data作为参数传递给它;
5.页面unload的时候,需要调用remove方法将自己从clients列表中去除。
另外,每个页面都必须有一个定时器,用来更新clients列表,检查新消息以及删掉已读消息。
新版本的webim应该会采用这种方案来实现多页面聊天,具体代码我也没写完,不过从下面的demo已经可以看到基本思想:打开多个页面,在文本框写些文字,点击同步按钮,其它页面会同步更新文本框。
该方案的让人头疼的是用什么做本地存储:userData需要页面完全一致才能使用;globalStorage只有firefox和ie8才支持;flash、google gear需要装插件,database storage是html5里的内容也没几家支持。这样看来似乎只有session cookie比较靠谱,但众所周知每次与服务器的交互都会带上cookie,cookie本身的容量也很有限。但是,相比较每个页面都轮询服务器而言,就算用cookie存也还是值得的。
3 Responses to WebIM开发之多页面数据同步
doyi
09月 3rd, 2009 at 4:58 pm
相当于在没锁的情况下多线程读写同一资源,不靠谱。。。
Jerry Qu
09月 3rd, 2009 at 11:30 pm
@doyi,感谢多益的回复,这样确实有并发读写的隐患,在cookie里加一个标识位能起到一些作用。总之,这个设想还很原始,要好好再设计下。
davidlin
10月 5th, 2009 at 12:39 pm
可以考虑在本地创建txt吧