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批量修改文件编码格式
Jan 22 NodeJs
nodejs调用cmd命令实现复制目录
May 04 NodeJs
Nodejs的express使用教程
Nov 23 NodeJs
NodeJs的优势和适合开发的程序
Aug 14 NodeJs
Nodejs中解决cluster模块的多进程如何共享数据问题
Nov 10 NodeJs
nodejs搭建本地服务器并访问文件的方法
Mar 03 NodeJs
详解nodejs微信公众号开发——6.自定义菜单
Apr 13 NodeJs
CentOS 安装NodeJS V8.0.0的方法
Jun 15 NodeJs
nodejs实现爬取网站图片功能
Dec 14 NodeJs
NodeJS实现不可逆加密与密码密文保存的方法
Mar 16 NodeJs
nodejs+mongodb aggregate级联查询操作示例
Mar 17 NodeJs
详解nodejs http请求相关总结
Mar 31 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
PHP中func_get_args(),func_get_arg(),func_num_args()的区别
2013/09/30 PHP
CentOS系统中PHP安装扩展的方式汇总
2017/04/09 PHP
Laravel 创建可以传递参数 Console服务的例子
2019/10/14 PHP
33个优秀的 jQuery 图片展示插件分享
2012/03/14 Javascript
动态加载脚本提升javascript性能
2014/02/24 Javascript
javascript动态修改Li节点值的方法
2015/01/20 Javascript
js中函数声明与函数表达式
2015/06/03 Javascript
JS组件Bootstrap Select2使用方法解析
2016/05/30 Javascript
js实现可旋转的立方体模型
2016/10/16 Javascript
node操作mysql数据库实例详解
2017/03/17 Javascript
ES6中参数的默认值语法介绍
2017/05/03 Javascript
vue.js实例todoList项目
2017/07/07 Javascript
vue微信分享出来的链接点开是首页问题的解决方法
2018/11/28 Javascript
如何区分vue中的v-show 与 v-if
2020/09/08 Javascript
Python实现截屏的函数
2015/07/25 Python
Python中pygal绘制雷达图代码分享
2017/12/07 Python
tensorflow创建变量以及根据名称查找变量
2018/03/10 Python
PyQt5每天必学之单行文本框
2018/04/19 Python
Pandas中resample方法详解
2019/07/02 Python
python实现H2O中的随机森林算法介绍及其项目实战
2019/08/29 Python
Python中Yield的基本用法
2020/10/18 Python
移动端html5模拟长按事件的实现方法
2018/09/30 HTML / CSS
加拿大时尚潮流大码女装购物网站:Addition Elle
2018/04/02 全球购物
法国一家芭蕾舞鞋公司:Repetto
2018/11/12 全球购物
美赞臣营养马来西亚旗舰店:Enfagrow马来西亚
2019/07/26 全球购物
美国名牌香水折扣网站:Hottperfume
2021/02/10 全球购物
我的理想演讲稿
2014/04/30 职场文书
银行党员批评与自我批评
2014/10/15 职场文书
辞职信的写法
2015/02/27 职场文书
机修车间主任岗位职责
2015/04/08 职场文书
学校艾滋病宣传活动总结
2015/05/09 职场文书
辩论赛开场白大全(主持人+辩手)
2015/05/29 职场文书
退休欢送会主持词
2015/07/01 职场文书
mysql中int(3)和int(10)的数值范围是否相同
2021/10/16 MySQL
分享MySQL常用 内核 Debug 几种常见方法
2022/03/17 MySQL
mysql中DCL常用的用户和权限控制
2022/03/31 MySQL