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中操作mysql数据库示例
Dec 20 NodeJs
使用nodejs开发cli项目实例
Jun 03 NodeJs
Nodejs进阶:核心模块net入门学习与实例讲解
Nov 21 NodeJs
Nodejs基于LRU算法实现的缓存处理操作示例
Mar 17 NodeJs
nodejs使用express创建一个简单web应用
Mar 31 NodeJs
nodejs获取微信小程序带参数二维码实现代码
Apr 12 NodeJs
NodeJS自定义模块写法(详解)
Jun 27 NodeJs
深入解析nodejs HTTP服务
Jul 25 NodeJs
详解使用PM2管理nodejs进程
Oct 24 NodeJs
nodejs中实现修改用户路由功能
May 24 NodeJs
NodeJs生成sitemap站点地图的方法示例
Jun 11 NodeJs
node快速搭建后台的实现步骤
Feb 18 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 数据库树的遍历方法
2009/02/06 PHP
php表单提交问题的解决方法
2011/04/12 PHP
php7 list()、session及其他模块的修改实例分析
2020/05/25 PHP
JS 控制小数位数的实现代码
2011/08/02 Javascript
如何使用Javascript获取距今n天前的日期
2013/07/08 Javascript
jQuery表单获取和失去焦点输入框提示效果的实例代码
2013/08/01 Javascript
JS实现侧悬浮浮动实例代码
2013/11/29 Javascript
使用js判断当前时区TimeZone是否是夏令时
2014/02/23 Javascript
AMD异步模块定义介绍和Require.js中使用jQuery及jQuery插件的方法
2014/06/06 Javascript
3种Jquery限制文本框只能输入数字字母的方法
2014/12/03 Javascript
javascript实现base64 md5 sha1 密码加密
2015/09/09 Javascript
AngularJS实现Input格式化的方法
2016/11/07 Javascript
基于vue.js实现图片轮播效果
2016/12/01 Javascript
利用JS轻松实现获取表单数据
2016/12/06 Javascript
AngularJS实现使用路由切换视图的方法
2017/01/24 Javascript
Mobile Web开发基础之四--处理手机设备的横竖屏问题
2017/08/11 Javascript
用jquery获取select标签中选中的option值及文本的示例
2018/01/25 jQuery
es6 super关键字的理解与应用实例分析
2020/02/15 Javascript
web.py在模板中输出美元符号的方法
2014/08/26 Python
Python实现从URL地址提取文件名的方法
2015/05/15 Python
python enumerate函数的使用方法总结
2017/11/15 Python
python之消除前缀重命名的方法
2018/10/21 Python
10分钟用python搭建一个超好用的CMDB系统
2019/07/17 Python
Python3实现二叉树的最大深度
2019/09/30 Python
python读取图片的几种方式及图像宽和高的存储顺序
2020/02/11 Python
手把手教你配置JupyterLab 环境的实现
2021/02/02 Python
Deichmann英国:德国鞋类零售商
2021/01/30 全球购物
德国珠宝和配件商店:Styleserver
2021/02/23 全球购物
社区包粽子活动方案
2014/01/21 职场文书
食品采购员岗位职责
2014/04/14 职场文书
诚信的演讲稿范文
2014/05/12 职场文书
认错检讨书
2014/10/02 职场文书
离职感谢信怎么写
2015/01/22 职场文书
2015年教师工作总结范文
2015/03/31 职场文书
Mongo服务重启异常问题的处理方法
2021/07/01 MongoDB
利用JavaScript写一个简单计算器
2021/11/27 Javascript