为HTTP请求设置时间限制
当XMLHttpRequest请求没有成功时,在指定的时间段后显示有帮助的信息。
XMLHttpRequest对象会打开一组异常,这些异常是连接服务器失败时由JavaScript程序产生的。为什么会发生?网络延迟可能是问题所在,或者服务器出现了错误。你并不知道你的用户连接得有多快,服务器端程序也可能因为处理大量同步请求而陷于停滞,甚至完全中断。无论如何,作为一个开发者,你希望控制用户等待多长的时间来获得应用的响应。就我们所知,用户不愿意等待太长时间,超过几秒钟通常被认为是不可接受的。
本hack在显示友好的信息给用户前花10秒钟等待服务器响应。
提示:如果你愿意,可以是5秒或更少,或者60秒。最大可容忍的等待时间依赖于你的应用场景、你的用户测试结果,以及其他因素。例如,比起依赖于应用并对其投入大量时间的局域网用户,一个普通的公众客户可能更希望一个活跃的应用,不愿意花时间等待。
本hack使用顶层window对象的名为setTimeout()的JavaScript方法。
提示:感谢Joshua Gitlin及他在http://www.xml.com/ pub/a/2005/05/11/ajax-error.html所发表的文章,它给本技术提供了很好的提示。
你可以不需要在前面冠以window对象而使用window对象的方法。换句话说,只使用setTimeout()和使用window.setTimeout()一样能正常工作。
setTimeout()接收一个函数名或者函数体作为第一个参数,另一个参数是调用方法前要等待的毫秒数(千分之一秒)。它返回一个数字值,这个数字值能用于取消函数调用。待会儿将会为你展示这些;同时,这里有段代码http_request.js,它封装了XMLHttpRequest对象的初始化以及用法。(“使用自己的库封装XMLHttpRequest”[Hack #3]可见更完整的解释。)
回想一下 setTimeout()每隔10秒钟调用一次timesUp()函数。如果过了10秒钟,request.readyState ==4没有返回true(代表HTTP请求完成),那么清除时限(timeout),timesUp()中止请求并显示一个alert窗口给用户。这个动作停止了请求;用户不得不重新启动和应用的交互以发起另一个请求。
提示:如果你想将时限设为3秒,例如,安装代码看起来如下:
timeoutId = setTimeout(timesUp,3000);
如果HTTP请求无故障地成功完成,代码将前面提到的timeoutId作为参数来调用clearTimeout()。这个动作立即取消了timesUp()的调用,让应用程序继续执行,做它想做的工作。
当XMLHttpRequest请求没有成功时,在指定的时间段后显示有帮助的信息。
XMLHttpRequest对象会打开一组异常,这些异常是连接服务器失败时由JavaScript程序产生的。为什么会发生?网络延迟可能是问题所在,或者服务器出现了错误。你并不知道你的用户连接得有多快,服务器端程序也可能因为处理大量同步请求而陷于停滞,甚至完全中断。无论如何,作为一个开发者,你希望控制用户等待多长的时间来获得应用的响应。就我们所知,用户不愿意等待太长时间,超过几秒钟通常被认为是不可接受的。
本hack在显示友好的信息给用户前花10秒钟等待服务器响应。
提示:如果你愿意,可以是5秒或更少,或者60秒。最大可容忍的等待时间依赖于你的应用场景、你的用户测试结果,以及其他因素。例如,比起依赖于应用并对其投入大量时间的局域网用户,一个普通的公众客户可能更希望一个活跃的应用,不愿意花时间等待。
本hack使用顶层window对象的名为setTimeout()的JavaScript方法。
提示:感谢Joshua Gitlin及他在http://www.xml.com/ pub/a/2005/05/11/ajax-error.html所发表的文章,它给本技术提供了很好的提示。
你可以不需要在前面冠以window对象而使用window对象的方法。换句话说,只使用setTimeout()和使用window.setTimeout()一样能正常工作。
setTimeout()接收一个函数名或者函数体作为第一个参数,另一个参数是调用方法前要等待的毫秒数(千分之一秒)。它返回一个数字值,这个数字值能用于取消函数调用。待会儿将会为你展示这些;同时,这里有段代码http_request.js,它封装了XMLHttpRequest对象的初始化以及用法。(“使用自己的库封装XMLHttpRequest”[Hack #3]可见更完整的解释。)
下面就是代码,重新改进以包含setTimeout()和一个新函数timesUp():
var request = null;
var timeoutId;
/* request对象的封装函数。
参数:
reqType: HTTP请求类型,如GET 或 POST。
url: 服务器端程序的URL
asynch: 是否异步发送请求
respHandle: 处理响应的函数名
arguments[4]所代表的第5个参数是POST请求要发送的数据
*/
function httpRequest(reqType,url,asynch,respHandle){
//基于Mozilla的浏览器
if(window.XMLHttpRequest){
request = new XMLHttpRequest();
} else if (window.ActiveXObject){
request=new ActiveXObject("Msxml2.XMLHTTP");
if (! request){
request=new ActiveXObject("Microsoft.XMLHTTP");
}
}
//如果ActiveXObject没有被初始化,我们会测试到一个null的request
if(request) {
//如果请求类型是POST,那么第5个参数是被发送的数据
if(reqType.toLowerCase() != "post") {
initReq(reqType,url,asynch,respHandle);
} else {
//被发送的数据
var args = arguments[4];
if(args != null && args.length > 0){
initReq(reqType,url,asynch,respHandle,args);
}
}
} else {
alert("Your browser does not permit the use of all "+
"of this application's features!");
}
}
/*初始化已经构造的request对象 */
function initReq(reqType,url,bool,respHandle){
try{
/*指定处理HTTP响应的函数 */
request.onreadystatechange=respHandle;
request.open(reqType,url,bool);
timeoutId = setTimeout(timesUp,10000);
//如果请求类型是POST,那么第5个参数是被发送的数据
if(reqType.toLowerCase() == "post") {
request.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded; charset=UTF-8");
request.send(arguments[4]);
} else {
request.send(null);
}
} catch (errv) {
alert(
"The application cannot contact "+
"the server at the moment. "+
"Please try again in a few seconds.\n"+
"Error detail: "+errv.message);
}
}
function timesUp(){
//见下...
request.open()方法为发起一个HTTP连接准备了XMLHttpRequest对象。然后代码在请求被发送之前调用setTimeout()。下面是余下的代码:
/* XMLHttpRequest的事件处理器;这个函数并不是
http_request.js的一部分,但是将被定义在另一个使用
http_request.js的代码文件里,就像在
httpRequest("GET",url,true,handleReq)一样 */
function handleReq(){
if(request.readyState == 4){
//timeoutId 在http_request.js中声明
//但在这儿能作为一个全局变量引用
clearTimeout(timeoutId);
if(request.status == 200){
//做些有趣的事...
}
}//结束外部的if
}
function timesUp(){
request.abort();
alert("A problem occurred with communicating with "+
"the server program. Please make sure you are connected "+
"to the Internet and try again in a few moments.");
}
回想一下 setTimeout()每隔10秒钟调用一次timesUp()函数。如果过了10秒钟,request.readyState ==4没有返回true(代表HTTP请求完成),那么清除时限(timeout),timesUp()中止请求并显示一个alert窗口给用户。这个动作停止了请求;用户不得不重新启动和应用的交互以发起另一个请求。
提示:如果你想将时限设为3秒,例如,安装代码看起来如下:
timeoutId = setTimeout(timesUp,3000);
如果HTTP请求无故障地成功完成,代码将前面提到的timeoutId作为参数来调用clearTimeout()。这个动作立即取消了timesUp()的调用,让应用程序继续执行,做它想做的工作。