nodejs发送http请求时遇到404长时间未响应的解决方法


Posted in NodeJs onDecember 10, 2017

通常,我们在使用nodejs发送http请求时,一旦遇到404响应,nodejs内部会一直请求下去,直到超出它自己设定的响应时长(最让人恶心的地方就是这个时长还是没法修改的。)很多人在这里碰到了麻烦。

我是在做arcgis地图项目的时候,客户提出需要使用天地图提供的底图服务,当时我直接使用silverlight客户端的Arcgis API进行http请求(同样是内部请求,不开源的东西就是这么让人郁闷),同样碰到了一个进度条一直卡在那的问题。经过调试发现,是由于底图加载请求超时的缘故,和nodejs一样,silverlight一直在进行请求直到超出它自己设定的响应时限。

于是,我当时正好有业余接触nodejs,觉得这个东西性能应该是不错的,至少比tomcat+java之流要好一些。于是,我着手写了一个nodejs的代理服务,用来请求天地图的底图。我当时以为nodejs碰到404时能直接结束请求,但是呢,这个问题好像是行业规范似的,它竟然也和silverlight一样不断的请求……索性上网查了会资料,得出了以下这两段代码,解决了这个一直请求404的问题。

function proxyTDTMapData(img,level,row,col){ 
  var that = this,request = null,param = img.replace('_w',''); 
  var filename = tdtimgDir+'/'+img+'_'+level+'_'+row+'_'+col+'.png'; 
  path.exists(filename, function(exists) { 
    if (exists) { 
      readFileEntry(filename,that.res); 
    }else{ 
      var url = "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("have a response!"); 
        if(200 == response.statusCode){ 
          var size = 0; 
          var chunks = []; 
          response.on('data', function(chunk){ 
            size += chunk.length; 
            chunks.push(chunk); 
          }); 
          response.on('end', function(){ 
            var data = 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); 
      }); 
    } 
  }); 
   
   
 }
function httpGetWithTimeoutSupport(options, timeout, callback) { 
  var timeoutEvent; 
 
  var req = 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("res error catch"); 
      }catch(e){ 
       
      } 
    }); 
    callback(res); 
  }); 
 
  req.on("timeout", function() { 
    //console.log("request emit timeout received"); 
    try{ 
      if (req.res) { 
        req.res.emit("abort"); 
      } 
      clearTimeout(timeoutEvent); 
      req.abort(); 
    }catch(e){ 
      //console.log("req timeout failed!"); 
    } 
  }); 
  req.on("error",function(){ 
    try{ 
      //console.log("req error catch"); 
    }catch(e){ 
     
    } 
  }); 
  timeoutEvent = setTimeout(function() { 
    try{ 
      req.emit("timeout"); 
    }catch(e){ 
      //console.log("timeout failed!"); 
    } 
  }, timeout); 
 
  return req; 
}

其原理就是利用nodejs请求的几个事件与计时器,一旦超出设定的响应时长则立马终结请求。如此,进度条一直卡着的问题解决了。
细心的读者可能看到了

path.exists(filename, function(exists) { 
    if (exists) { 
      readFileEntry(filename,that.res); 
    }else{...});

这段代码,其实这里做了一下服务端的图片缓存,一旦加载过的底图图片,直接从本地读取,极大的加快了地图的访问速度(这个在效率上提升了至少10倍)。
至于Arcgis API for Silverlight 是如何实现天地图底图以及其它底图服务(比如非标准墨卡托的地方坐标系底图服务)加载的呢?请听我下回分解。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

NodeJs 相关文章推荐
nodejs中转换URL字符串与查询字符串详解
Nov 26 NodeJs
轻松创建nodejs服务器(8):非阻塞是如何实现的
Dec 18 NodeJs
nodeJS代码实现计算交社保是否合适
Mar 09 NodeJs
nodejs实现获取某宝商品分类
May 28 NodeJs
nodejs实现获取当前url地址及url各种参数值
Jun 25 NodeJs
NodeJS仿WebApi路由示例
Feb 28 NodeJs
nodejs实现邮件发送服务实例分享
Mar 29 NodeJs
NodeJs中express框架的send()方法简介
Jun 20 NodeJs
Windows下使用Nodejs运行js的方法
Sep 02 NodeJs
nodejs发送http请求时遇到404长时间未响应的解决方法
Dec 10 NodeJs
Nodejs下使用gm圆形裁剪并合成图片的示例
Feb 22 NodeJs
nodejs中实现修改用户路由功能
May 24 NodeJs
NodeJs实现定时任务的示例代码
Dec 05 #NodeJs
windows系统下更新nodejs版本的方案
Nov 24 #NodeJs
nodejs项目windows下开机自启动的方法
Nov 22 #NodeJs
使用nodeJs来安装less及编译less文件为css文件的方法
Nov 20 #NodeJs
NodeJS实现视频转码的示例代码
Nov 18 #NodeJs
详解NODEJS基于FFMPEG视频推流测试
Nov 17 #NodeJs
nodejs async异步常用函数总结(推荐)
Nov 17 #NodeJs
You might like
编译问题
2006/10/09 PHP
php $_SERVER windows系统与linux系统下的区别说明
2014/02/14 PHP
php自定义函数实现二维数组排序功能
2016/07/20 PHP
基于jquery的复制网页内容到WORD的实现代码
2011/02/16 Javascript
js获取dom的高度和宽度(可见区域及部分等等)
2013/06/13 Javascript
jquery禁用右键示例
2014/04/28 Javascript
基于jQuery通过jQuery.form.js插件实现异步上传
2015/12/13 Javascript
JS中frameset框架弹出层实例代码
2016/04/01 Javascript
避免jQuery名字冲突 noConflict()方法
2016/07/30 Javascript
简洁实用的BootStrap jQuery手风琴插件
2016/08/31 Javascript
如何使用Vuex+Vue.js构建单页应用
2016/10/27 Javascript
JavaScript运动框架 解决防抖动问题、悬浮对联(二)
2017/05/17 Javascript
vue实现移动端图片裁剪上传功能
2020/08/18 Javascript
Vue页面骨架屏注入方法
2018/05/13 Javascript
vue中axios的封装问题(简易版拦截,get,post)
2018/06/15 Javascript
使用weixin-java-tools完成微信授权登录、微信支付的示例
2018/09/26 Javascript
Node.js中读取TXT文件内容fs.readFile()用法
2018/10/10 Javascript
解决node-sass偶尔安装失败的方法小结
2018/12/05 Javascript
Vue中使用create-keyframe-animation与动画钩子完成复杂动画
2019/04/09 Javascript
ios中视频的最后一桢问题解决
2019/05/14 Javascript
微信sdk实现禁止微信分享(使用原生php实现)
2019/11/15 Javascript
[43:47]完美世界DOTA2联赛PWL S3 LBZS vs Phoenix 第一场 12.09
2020/12/11 DOTA
使用python实现rsa算法代码
2016/02/17 Python
pycharm设置注释颜色的方法
2018/05/23 Python
Python带动态参数功能的sqlite工具类
2018/05/26 Python
Python线性拟合实现函数与用法示例
2018/12/13 Python
详解Python计算机视觉 图像扭曲(仿射扭曲)
2019/03/27 Python
pytorch下使用LSTM神经网络写诗实例
2020/01/14 Python
PyQt5 如何让界面和逻辑分离的方法
2020/03/24 Python
通过实例解析Python文件操作实现步骤
2020/09/21 Python
文科生自我鉴定
2014/02/15 职场文书
党的群众路线教育实践活动心得体会
2014/03/03 职场文书
乡镇群众路线整改落实情况汇报
2014/10/28 职场文书
八年级地理课件资料及考点知识分享
2019/08/30 职场文书
用PYTHON去计算88键钢琴的琴键频率和音高
2022/04/10 Python
Nginx配置根据url参数重定向
2022/04/11 Servers