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实现的一个简单udp广播服务器、客户端
Sep 25 NodeJs
深入nodejs中流(stream)的理解
Mar 27 NodeJs
Ajax异步文件上传与NodeJS express服务端处理
Apr 01 NodeJs
详解nodejs通过代理(proxy)发送http请求(request)
Sep 22 NodeJs
使用npm安装最新版本nodejs
Jan 18 NodeJs
nodejs连接mysql数据库及基本知识点详解
Mar 20 NodeJs
nodejs express配置自签名https服务器的方法
May 22 NodeJs
nodejs 十六进制字符串型数据与btye型数据相互转换
Jul 30 NodeJs
NodeJS实现自定义流的方法
Aug 01 NodeJs
nodejs分离html文件里面的js和css的方法
Apr 09 NodeJs
nodejs实现日志读取、日志查找及日志刷新的方法分析
May 20 NodeJs
nodejs log4js 使用详解
May 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与XML的PDF文档生成技术
2006/10/09 PHP
PHP通用检测函数集合
2006/11/25 PHP
PHP 变量的定义方法
2010/01/26 PHP
PHP高级对象构建 多个构造函数的使用
2012/02/05 PHP
php开启与关闭错误提示适用于没有修改php.ini的权限
2014/10/16 PHP
万能的php分页类
2017/07/06 PHP
PHP聊天室简单实现方法详解
2018/12/08 PHP
js判断横竖屏及禁止浏览器滑动条示例
2014/04/29 Javascript
使用jquery组件qrcode生成二维码及应用指南
2015/02/22 Javascript
Javascript中级语法快速入手
2016/07/30 Javascript
js 事件的传播机制(实例讲解)
2017/07/20 Javascript
基于jQuery选择器之表单对象属性筛选选择器的实例
2017/09/19 jQuery
使用百度地图实现地图网格的示例
2018/02/06 Javascript
总结JavaScript在IE9之前版本中内存泄露问题
2018/04/28 Javascript
小程序scroll-view安卓机隐藏横向滚动条的实现详解
2019/05/16 Javascript
Python脚本获取操作系统版本信息
2016/12/17 Python
使用python对excle和json互相转换的示例
2018/10/23 Python
Python装饰器用法实例分析
2019/01/14 Python
django的ORM操作 增加和查询
2019/07/26 Python
Python2与Python3的区别详解
2020/02/09 Python
解决tensorflow 释放图,删除变量问题
2020/06/23 Python
PyCharm+PyQt5+QtDesigner配置详解
2020/08/12 Python
Java Unsafe类实现原理及测试代码
2020/09/15 Python
深入浅出CSS3 background-clip,background-origin和border-image教程
2011/01/27 HTML / CSS
HTML5 Canvas旋转动画的2个代码例子(一个旋转的太极图效果)
2014/04/10 HTML / CSS
服装厂厂长职责
2013/12/16 职场文书
管理岗位竞聘演讲稿
2014/08/18 职场文书
检查机关党的群众路线个人整改措施
2014/10/04 职场文书
2014年财务工作总结与计划
2014/12/08 职场文书
平安建设汇报材料
2014/12/29 职场文书
大学生个人简历自我评价
2015/03/11 职场文书
Mysql数据库命令大全
2021/05/26 MySQL
python中opencv实现图片文本倾斜校正
2021/06/11 Python
《帝国时代4》赛季预告 新增内容编译器可创造地图
2022/04/03 其他游戏
python blinker 信号库
2022/05/04 Python
Python可视化神器pyecharts之绘制地理图表练习
2022/07/07 Python