Xu Wenhao

View on GitHub
29 January 2006

不要滥用Ajax,搞清楚状况先

by Xu Wenhao

决定开始写一些技术小文章,一是总结过去遇到的一些问题的经验,而是锻炼一下写技术文章的能力,争取过两年能混点稿费啥的。

Ajax在过去的一年,可谓大红大紫,以至于很多时候,我们在考虑到减少网络流量的时候,减少页面刷新的时候,第一反应都是,“用Ajax实现吧”。

但是,且慢,是不是所有的都有必要用到Ajax呢?是不是有些时候,不用Ajax,其实一样能够简单有效的实现需求呢?当然,前一段时间,我就遇到这么一个例子。

业务需求是这样的,我们为某公司内部的Call Center建立一个Knowledge Base(以下简称为KB),以帮助接线员迅速查找到所需要的产品资料,告诉用户。用户的产品资料是一个三层的结构,包括Brand, Model和Trim,约有20个左右的Brand,每个Brand下有多个Model,每个Model下还有数个Trim,每个Trim下,则包含了大量的所需要的产品资料信息。接线员在使用KB的时候,先从一个select box选择Brand,然后再从另一个select box中选择该Brand下的Model,最后再从一个select box中选择到该Model下的Trim,最后点击一个button,获取该Trim的所有信息。

当时在接到这个KB的时候,时间紧迫,于是,在熬了一个通宵之后,做出了第一个版本,将结果发到美国,等待反馈,反馈的结果则是,页面performance不够好,每次选完Trim之后等待页面刷新,要很长时间。

这个结果在我们的预料之中,因为,由于时间上的限制,在实现Brand,Model,Trim的三层select box的动态刷新的时候,没有自己从头实现,而是参考了另一个项目组A的代码。实现的方法是在javascript通过二维数组保存所有的Brand,Model和Trim的关联信息,动态生成select box中的内容。由于我们的Brand,Model,Trim的关联信息远远比A的数量要多,因为A中只有Brand和Model的两层关联信息,所以,在他们那边不成问题的页面大小问题,在我们这边就成了大问题。事实上,我们存在javascript数组中的信息,高达300k,而整个页面的其他部分的大小之和,也不超过30k。

问题应该如何解决呢?方案有很多种,比如,我们可以用Ajax重写三层select box的刷新,但是,时间有限,代码改动也会比较大;或者,我们可以将javascript的关联信息,单独写在一个js文件中,这样,一般情况下,浏览器会将其存在cache中,每次数据传输的流量就不会过大,但是cache本身就不牢靠,而且这样在后台数据更新了之后,浏览其中可能还是过时的cache信息。

考虑再三之后,和同事讨论研究了一下,决定采用Ajax来写获得Trim具体信息的部分,这样,只需要将原来的页面刷新中,采用form提交,刷新整个页面,改成通过发送一个ajax-request,由ajax-response更新Trim具体信息区域即可,这样,在第一次获得页面之后,以后都不用重新从服务器端去读取Brand,Model,Trim的层级关联信息,也就解决了performance的问题。

于是,我采用了rico包,花了一个下午实现了这个功能,但是发现还是有问题,由于rico包对特殊字符的支持不好,我们不得不专门写了个程序,将所有从后台传递的字符转成unicode再传过来,看起来,问题到这里已经解决了,于是测试一下,似乎有些时候行,有些时候不行,捣腾了好一会儿,没有修改代码,似乎,问题是解决了,但是心里还是不放心,因为之前用rico写中文站点的时候,遇到过在Firefox下即使所有字符都转成unicode,仍然有些字符不能传到前台的问题。而大量的Trim信息,我们不可能手工一个一个测过来,写脚本测,时间也不太充裕了……

最后,我们怎么解决问题的呢?其实很简单,我们为什么要用Ajax?事实上,我们最后是采用了frameset的办法,一个frame里放的是三层关联信息的select box,另一个frame里,放Trim的具体信息页面,只要将上面的form的target设为下面的form,那么每次就是刷新Trim的具体信息,所需要的,只是将原来一个页面里的代码,放到两个frame里……而之前,我们为什么会去考虑到Ajax这种啥办法呢?

总结一下,之所以会花大量的时间去做无用功,一是习惯性的使用所谓的优秀技术,总觉得,啊,要用Ajax;二是没有仔细分析清楚需求,我们所要得,不是不刷新页面,而是减少数据传输量,刷不刷新页面,是无所谓的。事实上,在Web的设计和实现的时候,我们会遇到大量的类似问题,所以,分析需求,考虑到所有最简单最低级的技术,是很有价值的。有时候,我们要的是SEO,要google搜到我们,不能用Ajax;有时候,我们要良好的中文支持,最好别用Ajax;有时候,我们只是要减少数据传输量,framset已经足够。Ajax不是万能药,有种种的缺陷和限制,适用的情况,其实并没有那么多。

tags: