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的前后端分离的思考与实践(三)轻量级的接口配置建模框架
Sep 26 NodeJs
NodeJS Web应用监听sock文件实例
Feb 18 NodeJs
NodeJS 实现手机短信验证模块阿里大于功能
Jun 19 NodeJs
详解HTTPS 的原理和 NodeJS 的实现
Jul 04 NodeJs
nodejs模块学习之connect解析
Jul 05 NodeJs
nodejs中安装ghost出错的原因及解决方法
Oct 23 NodeJs
Mac 安装 nodejs方法(图文详细步骤)
Oct 30 NodeJs
使用nodejs+express实现简单的文件上传功能
Dec 27 NodeJs
关于Mac下安装nodejs、npm和cnpm的教程
Apr 11 NodeJs
基于Nodejs的Tcp封包和解包的理解
Sep 19 NodeJs
nodejs中函数的调用实例详解
Oct 31 NodeJs
详解NodeJs项目 CentOs linux服务器线上部署
Sep 16 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
在IIS上安装PHP4.0正式版
2006/10/09 PHP
使用eAccelerator加密PHP程序
2008/10/03 PHP
PHP针对中英文混合字符串长度判断及截取方法示例
2017/03/31 PHP
PHP中使用jQuery+Ajax实现分页查询多功能操作(示例讲解)
2017/09/17 PHP
laravel框架与其他框架的详细对比
2019/10/23 PHP
PHP设计模式入门之迭代器模式原理与实现方法分析
2020/04/26 PHP
JAVASCRIPT对象及属性
2007/02/13 Javascript
Javascript与flash交互通信基础教程
2008/08/07 Javascript
javascript中使用css需要注意的地方小结
2010/09/01 Javascript
javascript实现的使用方向键控制光标在table单元格中切换
2010/11/17 Javascript
jQuery EasyUI API 中文文档 DateTimeBox日期时间框
2011/10/16 Javascript
Jquery事件的连接使用示例
2013/06/18 Javascript
Jquery右下角抖动、浮动 实例代码(兼容ie6、FF)
2013/08/15 Javascript
JavaScript闭包实例讲解
2014/04/22 Javascript
Java中Timer的用法详解
2015/10/21 Javascript
Vue网页html转换PDF(最低兼容ie10)的思路详解
2017/08/24 Javascript
Vue利用路由钩子token过期后跳转到登录页的实例
2017/10/26 Javascript
Vue中图片Src使用变量的方法
2019/10/30 Javascript
Vue和React有哪些区别
2020/09/12 Javascript
浅谈vue使用axios的回调函数中this不指向vue实例,为undefined
2020/09/21 Javascript
python实现移位加密和解密
2019/03/22 Python
详解Python是如何实现issubclass的
2019/07/24 Python
python redis连接 有序集合去重的代码
2019/08/04 Python
Python整数与Numpy数据溢出问题解决
2019/09/11 Python
Centos7 下安装最新的python3.8
2019/10/28 Python
python 计算积分图和haar特征的实例代码
2019/11/20 Python
Python内置数据类型list各方法的性能测试过程解析
2020/01/07 Python
Python如何将字符串转换为日期
2020/07/31 Python
python使用建议技巧分享(三)
2020/08/18 Python
html5+css3之CSS中的布局与Header的实现
2014/11/21 HTML / CSS
使用CSS3 制作一个material-design 风格登录界面实例
2016/12/12 HTML / CSS
车辆工程专业求职信
2014/06/14 职场文书
单位委托书怎么写
2014/08/02 职场文书
社区精神文明建设汇报材料
2014/08/17 职场文书
教你用Java在个人电脑上实现微信扫码支付
2021/06/13 Java/Android
Android开发EditText禁止输入监听及InputFilter字符过滤
2022/06/10 Java/Android