首页 » 编写高质量代码:改善JavaScript程序的188个建议 » 编写高质量代码:改善JavaScript程序的188个建议全文在线阅读

《编写高质量代码:改善JavaScript程序的188个建议》建议150:优化Ajax开发的最佳实践

关灯直达底部

优化Ajax开发的最佳实践,有助于编写更加高效且健壮的Ajax代码。

(1)最小化调用

最小化调用数量的方法之一是将大量调用合并成少量调用。如果数据量相对较小,那么在大多数网络中,主要问题就在于延迟。延迟是浏览器真正获取服务器之间的连接所需的时间,有时它会占去大部分连接时间。用户所感受到的总延迟由几个部分组成,包括浏览器的缓存设置、DNS客户端,以及物理连接。

没有简易公式或代码片段供我们来了解如何减少Web应用程序调用。然而,只需一个简单的练习,就可以演示如何对从客户端到服务器的Ajax调用数量进行控制。考虑下面购买二手摩托车的Web应用程序。

首先,选择摩托车的年份,然后选择摩托车的构造,最后选择摩托车的型号。自始至终,Ajax一直在后台运行,更新Web应用程序中的下拉框来为用户过滤清单,以方便用户选择。

要开始这一练习,首先要为客户端及服务器创建一个简单图表(有一个文本框),然后为浏览器进行的Ajax调用画线,以从服务器获取用户数据。

可将对品牌和型号进行的调用合并到一个调用中,从而实现优化设计。不是对品牌进行一次调用,然后针对型号进行另一次调用,而是对型号进行缓存,这样,当用户选择品牌时,新代码只检索缓存中可用的型号列表。从本地缓存中获取数据要比从服务器获取相同数据快得多。回避额外的服务调用,避免服务调用的延迟。

新设计在浏览器与服务器之间的通信中去掉了一个调用。可利用下面代码进一步减少调用数量,其中的一些关键行可用于存储在数组中检索到的数据,供以后查找使用。


var choices=new Array;

function fillChoiceBoxes(year){

if(dojo.indexOf(choices,year)==-1){

//开始

}else{

choices[year]=result;

//Ajax调用结果

}

//调用函数

fillSelect(dojo.byId(/'makes/'),choices[year]);

}


在反复考虑两个不同的型号时,Web应用程序会使用本地缓存数据,而不是发起附加服务调用。仅缓存静态数据,至少在用户会话持续阶段是这样的。不要因为缓存了不应缓存的数据,而引起一系列问题。通过减少客户端与服务器之间的交互次数,以及在可能的情况下缓存数据,可以最小化调用次数。

(2)让数组变得很小

为提高数据处理性能,需要让服务器与客户端之间传输的数据尽量的小。为了高效地完成这一任务,必须控制从服务层到能够指定从服务器到客户端的消息类型的部分。有充足的理由证明,XML适合作为客户端到服务器的通用消息格式。理由之一是存在足够多的库或框架用于XML序列化。

然而,当与JSON对比时,XML显得很冗长,JSON则更加简明。目前已经有很多可以将消息方便地构建成JSON格式的库,这样就可以通过JSON的方式将数据从服务端传送到客户端。

如果服务器响应使用JSON,那么可通过提供一个参数来使用相同的客户端对象。仔细研究下面代码,其展示了使用XML的摩托车对象的表示。


<motorcycle>

<year>2012</year>

<make>Moto</make>

<model>Uberfast</model>

</motorcycle>


下面代码展示了使用JSON的摩托车对象。注意,它的代码量减少了大约25%(如果去掉空格)。


{/"motorcycle/":{

/"year/":/"2012/",

/"make/":/"Moto/",

/"model/":/"Uberfast/"

}

}


数据量变小了,不但从服务端到客户端的传输时间减少了,而且字符串的减小还节省了解析时间。在设计需要传输的数据时,其所包含的字符越少越好。

(3)预加载组件

可通过在Ajax调用中加载JavaScript文件与图像之类的组件来充分利用浏览器的缓存。需要注意的是,预加载JavaScript文件和图像,仅对那些开启缓存功能的用户有益,不过大多数用户的浏览器都开启了缓存功能。

要预加载外部JavaScript文件,可以将JavaScript文件包含在页面中,但是,只有当该页面很小且仅想优化少量资源时,才适合采用这一方式。例如,对于一个将工作流引入用户的相对轻量级的页面,预加载非常有用。考虑介绍最小化调用时的购买摩托车的例子,可在流的早期页面中预加载用于包含下拉框的页面的、包含全部Ajax代码的JavaScript代码。

在使用Ajax调用的方法更新图片时,预加载图像会提供很大便利。在预加载图像后,当用户将鼠标移动到元素时、从下拉框中进行选择时,或者单击按钮时,不必等待浏览器对图像进行检索。即使Ajax以异步方式发生,也需要花费一些时间将图像从服务器传送到客户端,并且图像在全部下载完毕之前不会在客户端中显示。例如,在下面示例中,当用户进行从清单中选择摩托车这一操作时,所采用的图像就是使用标准JavaScript代码预加载的。


<html>

<head><title></title></head>

<body>

<script type=/"text/Javascript/"language=/"Javascript/">

var img=new Image;

img.src="https://mysite/motocool.jpg";

</script>

</body>

</html>


在为页面预加载图像时,JavaScript的位置很重要,当然不希望因为在HTML中加入了JavaScript代码而影响页面的加载速度。一般的规则是,可将<script>元素当中的JavaScript代码放到HTML页面的最后部分,因为在考虑可同时下载多少资源时会发现浏览器的能力相对有限。如果可能,将脚本加到HTML页面的最后部分,从而帮助浏览器更快速地加载图像和其他资源。

在HTML 5中,可使用<script>标记的新async属性。这将告诉浏览器可以异步运行JavaScript代码,这样,JavaScript代码可以在页面中运行其他东西时执行。

(4)轻松处理错误

在JavaScript代码中定义的每个函数,都要假设会有恶意输入发生,因为防御性能强的代码比使用try catch语句所编写的代码更善于处理错误。例如,想使用JavaScript函数来根据用户输入进行计算,要在计算前检查输入。


function caculateDistance(source,dest){

if(!isNaN(source)||!isNaN(dest)){

dojo.byId(/"errors/").innerHTML=/"提示错误/";

}

}


即使代码具有防御能力,在适当的时候,也可使用try catch语句与错误回调。在下面示例中,JavaScript使用try catch语句来捕获错误。


function calculateDistance(source,dest){

try{

//执行计算...

}catch(error){

dojo.byId(/"errors/").innerHTML=/"提示错误/";

}

}


下面示例演示的是在调用Dojo Toolkit中所提供的xhrGet方法时对错误回调的使用。错误参数是可选的,因此可以很容易地跳过错误处理器的定义。


var args={

url:/"/js/dojo//NoSuchFile/",

handleAs:/"text/",

preventCache:true,

load:function(data){

//当加载成功时,执行计算

},

error:function(error){

dojo.byId(/"errors/").innerHTML=/"提示错误/";

}

}

var ajx=dojo.xhrGet(args);


如何处理页面上的错误,这既是个业务问题,又是个技术问题。适当的时候,客户能够提供在出现异常时有效的默认处理方式。

最后,不要在JavaScript提示对话框中显示错误描述。用户不是软件工程师,因此,这类提示信息对于用户来说没有任何意义。除了不要为用户提供无意义的信息之外,还要在提示对话框中要求客户取消该对话框,以返回页面。


function calculateDistance(source,dest){

try{

//执行计算

}catch(error){

//不要:

//alert(error.message);

//最好:

dojo.byId(/"errors/").innerHTML=/"提示错误/";

}

}


(5)使用现有工具

通过使用现有工具(框架与平台),可有效利用相应资源。大多数成熟的技术人员,会使用已在多个平台上测试过的,具有跨浏览器兼容性的工具。现有工具的大部分特性可用于部署到自己的项目中。

很多现有的优秀工具,除了支持Ajax调用之外,还能支持很多其他函数与特性,如动画等。jQuery是比较优秀的JavaScript库,它能提供全套的Ajax功能。jQuery还支持不同的消息格式及其他基于Ajax的方法,如getScript,它可用于下载并执行JavaScript文件,是预载组件最佳实践的起源。