nodejs发送http请求时遇到404长时间未响应的解决方法
通常,我们在使用nodejs发送http请求时,一旦遇到404响应,nodejs内部会一直请求下去,直到超出它自己设定的响应时长(最让人恶心的地方就是这个时长还是没法修改的。)很多人在这里碰到了麻烦。
我是在做arcgis地图项目的时候,客户提出需要使用天地图提供的底图服务,当时我直接使用silverlight客户端的ArcgisAPI进行http请求(同样是内部请求,不开源的东西就是这么让人郁闷),同样碰到了一个进度条一直卡在那的问题。经过调试发现,是由于底图加载请求超时的缘故,和nodejs一样,silverlight一直在进行请求直到超出它自己设定的响应时限。
于是,我当时正好有业余接触nodejs,觉得这个东西性能应该是不错的,至少比tomcat+java之流要好一些。于是,我着手写了一个nodejs的代理服务,用来请求天地图的底图。我当时以为nodejs碰到404时能直接结束请求,但是呢,这个问题好像是行业规范似的,它竟然也和silverlight一样不断的请求……索性上网查了会资料,得出了以下这两段代码,解决了这个一直请求404的问题。
functionproxyTDTMapData(img,level,row,col){
varthat=this,request=null,param=img.replace('_w','');
varfilename=tdtimgDir+'/'+img+'_'+level+'_'+row+'_'+col+'.png';
path.exists(filename,function(exists){
if(exists){
readFileEntry(filename,that.res);
}else{
varurl="http://t0.tianditu.com/"+img+"/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER="+param+"&tileMatrixSet=w&TileRow="+row+"&TileCol="+col+"&TileMatrix="+level+"&style=default&format=tiles";
httpGetWithTimeoutSupport(url,4000,function(response){
//console.log("havearesponse!");
if(200==response.statusCode){
varsize=0;
varchunks=[];
response.on('data',function(chunk){
size+=chunk.length;
chunks.push(chunk);
});
response.on('end',function(){
vardata=Buffer.concat(chunks,size);
that.res.writeHead(200,{
'Content-Type':'image/png',
'Content-Length':data.length,
'Accept-Ranges':'bytes',
'Server':'Microsoft-IIS/7.5',
'X-Powered-By':'ASP.NET'
});
that.res.write(data,"binary");
that.res.end();
fs.writeFile(tdtimgDir+'/'+img+'_'+level+'_'+row+'_'+col+'.png',data);
});
}else{
readFileEntry(mapDir+"/null.png",that.res);
}
}).on("error",function(){
readFileEntry(mapDir+"/null.png",that.res);
});
}
});
}
functionhttpGetWithTimeoutSupport(options,timeout,callback){
vartimeoutEvent;
varreq=http.get(options,function(res){
res.on("end",function(){
clearTimeout(timeoutEvent);
//console.log("end");
})
res.on("close",function(e){
clearTimeout(timeoutEvent);
//console.log("close");
})
res.on("abort",function(){
//console.log("abort");
});
res.on("error",function(){
try{
res.destory();
clearTimeout(timeoutEvent);
//console.log("reserrorcatch");
}catch(e){
}
});
callback(res);
});
req.on("timeout",function(){
//console.log("requestemittimeoutreceived");
try{
if(req.res){
req.res.emit("abort");
}
clearTimeout(timeoutEvent);
req.abort();
}catch(e){
//console.log("reqtimeoutfailed!");
}
});
req.on("error",function(){
try{
//console.log("reqerrorcatch");
}catch(e){
}
});
timeoutEvent=setTimeout(function(){
try{
req.emit("timeout");
}catch(e){
//console.log("timeoutfailed!");
}
},timeout);
returnreq;
}
其原理就是利用nodejs请求的几个事件与计时器,一旦超出设定的响应时长则立马终结请求。如此,进度条一直卡着的问题解决了。
细心的读者可能看到了
path.exists(filename,function(exists){
if(exists){
readFileEntry(filename,that.res);
}else{...});
这段代码,其实这里做了一下服务端的图片缓存,一旦加载过的底图图片,直接从本地读取,极大的加快了地图的访问速度(这个在效率上提升了至少10倍)。
至于ArcgisAPIforSilverlight是如何实现天地图底图以及其它底图服务(比如非标准墨卡托的地方坐标系底图服务)加载的呢?请听我下回分解。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。